summaryrefslogtreecommitdiff
path: root/chromium/chrome/browser/resources/bookmarks/debouncer.js
blob: feefd5ba2b7a8dec9596aed434fb9e36ec84a703 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import {assert} from 'chrome://resources/js/assert.m.js';
import {PromiseResolver} from 'chrome://resources/js/promise_resolver.m.js';

/**
 * @fileoverview A debouncer which fires the given callback after a delay. The
 * delay can be refreshed by calling restartTimeout. Resetting the timeout with
 * no delay moves the callback to the end of the task queue.
 */

export class Debouncer {
  /** @param {!function()} callback */
  constructor(callback) {
    /** @private {!function()} */
    this.callback_ = callback;
    /** @private {!Object} */
    this.timerProxy_ = window;
    /** @private {?number} */
    this.timer_ = null;
    /** @private {!function()} */
    this.boundTimerCallback_ = this.timerCallback_.bind(this);
    /** @private {boolean} */
    this.isDone_ = false;
    /** @private {!PromiseResolver} */
    this.promiseResolver_ = new PromiseResolver();
  }

  /**
   * Starts the timer for the callback, cancelling the old timer if there is
   * one.
   * @param {number=} delay
   */
  restartTimeout(delay) {
    assert(!this.isDone_);

    this.cancelTimeout_();
    this.timer_ =
        this.timerProxy_.setTimeout(this.boundTimerCallback_, delay || 0);
  }

  /**
   * @return {boolean} True if the Debouncer has finished processing.
   */
  done() {
    return this.isDone_;
  }

  /**
   * @return {!Promise} Promise which resolves immediately after the callback.
   */
  get promise() {
    return this.promiseResolver_.promise;
  }

  /**
   * Resets the debouncer as if it had been newly instantiated.
   */
  reset() {
    this.isDone_ = false;
    this.promiseResolver_ = new PromiseResolver();
    this.cancelTimeout_();
  }

  /**
   * Cancel the timer callback, which can be restarted by calling
   * restartTimeout().
   * @private
   */
  cancelTimeout_() {
    if (this.timer_) {
      this.timerProxy_.clearTimeout(this.timer_);
    }
  }

  /** @private */
  timerCallback_() {
    this.isDone_ = true;
    this.callback_.call();
    this.promiseResolver_.resolve();
  }
}