-
-
Notifications
You must be signed in to change notification settings - Fork 79
/
index.js
103 lines (80 loc) · 2.02 KB
/
index.js
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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
function debounce(function_, wait = 100, options = {}) {
if (typeof function_ !== 'function') {
throw new TypeError(`Expected the first parameter to be a function, got \`${typeof function_}\`.`);
}
if (wait < 0) {
throw new RangeError('`wait` must not be negative.');
}
// TODO: Deprecate the boolean parameter at some point.
const {immediate} = typeof options === 'boolean' ? {immediate: options} : options;
let storedContext;
let storedArguments;
let timeoutId;
let timestamp;
let result;
function run() {
const callContext = storedContext;
const callArguments = storedArguments;
storedContext = undefined;
storedArguments = undefined;
result = function_.apply(callContext, callArguments);
return result;
}
function later() {
const last = Date.now() - timestamp;
if (last < wait && last >= 0) {
timeoutId = setTimeout(later, wait - last);
} else {
timeoutId = undefined;
if (!immediate) {
result = run();
}
}
}
const debounced = function (...arguments_) {
if (
storedContext
&& this !== storedContext
&& Object.getPrototypeOf(this) === Object.getPrototypeOf(storedContext)
) {
throw new Error('Debounced method called with different contexts of the same prototype.');
}
storedContext = this; // eslint-disable-line unicorn/no-this-assignment
storedArguments = arguments_;
timestamp = Date.now();
const callNow = immediate && !timeoutId;
if (!timeoutId) {
timeoutId = setTimeout(later, wait);
}
if (callNow) {
result = run();
}
return result;
};
Object.defineProperty(debounced, 'isPending', {
get() {
return timeoutId !== undefined;
},
});
debounced.clear = () => {
if (!timeoutId) {
return;
}
clearTimeout(timeoutId);
timeoutId = undefined;
};
debounced.flush = () => {
if (!timeoutId) {
return;
}
debounced.trigger();
};
debounced.trigger = () => {
result = run();
debounced.clear();
};
return debounced;
}
// Adds compatibility for ES modules
module.exports.debounce = debounce;
module.exports = debounce;