summaryrefslogtreecommitdiffstats
path: root/devtools/shared/throttle.js
blob: 85d0514f984c9795bad70bef6d4bdeaa02e235f9 (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
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

"use strict";

/**
 * From underscore's `_.throttle`
 * http://underscorejs.org
 * (c) 2009-2014 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
 * Underscore may be freely distributed under the MIT license.
 *
 * Returns a function, that, when invoked, will only be triggered at most once during a
 * given window of time. The throttled function will run as much as it can, without ever
 * going more than once per wait duration.
 *
 * @param  {Function} func
 *         The function to throttle
 * @param  {number} wait
 *         The wait period
 * @param  {Object} scope
 *         The scope to use for func
 * @return {Function} The throttled function
 */
function throttle(func, wait, scope) {
  let args, result;
  let timeout = null;
  let previous = 0;

  const later = function () {
    previous = Date.now();
    timeout = null;
    result = func.apply(scope, args);
    args = null;
  };

  const throttledFunction = function () {
    const now = Date.now();
    const remaining = wait - (now - previous);
    args = arguments;
    if (remaining <= 0) {
      clearTimeout(timeout);
      timeout = null;
      previous = now;
      result = func.apply(scope, args);
      args = null;
    } else if (!timeout) {
      timeout = setTimeout(later, remaining);
    }
    return result;
  };

  function cancel() {
    if (timeout) {
      clearTimeout(timeout);
      timeout = null;
    }
    previous = 0;
    args = undefined;
    result = undefined;
  }

  function flush() {
    if (!timeout) {
      return result;
    }
    previous = 0;
    return throttledFunction();
  }

  throttledFunction.cancel = cancel;
  throttledFunction.flush = flush;

  return throttledFunction;
}

exports.throttle = throttle;