You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
60 lines
1.5 KiB
60 lines
1.5 KiB
1 month ago
|
'use strict';
|
||
|
|
||
|
const DEBOUNCE_DEFAULTS = {
|
||
|
trailing: true
|
||
|
};
|
||
|
function debounce(fn, wait = 25, options = {}) {
|
||
|
options = { ...DEBOUNCE_DEFAULTS, ...options };
|
||
|
if (!Number.isFinite(wait)) {
|
||
|
throw new TypeError("Expected `wait` to be a finite number");
|
||
|
}
|
||
|
let leadingValue;
|
||
|
let timeout;
|
||
|
let resolveList = [];
|
||
|
let currentPromise;
|
||
|
let trailingArgs;
|
||
|
const applyFn = (_this, args) => {
|
||
|
currentPromise = _applyPromised(fn, _this, args);
|
||
|
currentPromise.finally(() => {
|
||
|
currentPromise = null;
|
||
|
if (options.trailing && trailingArgs && !timeout) {
|
||
|
const promise = applyFn(_this, trailingArgs);
|
||
|
trailingArgs = null;
|
||
|
return promise;
|
||
|
}
|
||
|
});
|
||
|
return currentPromise;
|
||
|
};
|
||
|
return function(...args) {
|
||
|
if (currentPromise) {
|
||
|
if (options.trailing) {
|
||
|
trailingArgs = args;
|
||
|
}
|
||
|
return currentPromise;
|
||
|
}
|
||
|
return new Promise((resolve) => {
|
||
|
const shouldCallNow = !timeout && options.leading;
|
||
|
clearTimeout(timeout);
|
||
|
timeout = setTimeout(() => {
|
||
|
timeout = null;
|
||
|
const promise = options.leading ? leadingValue : applyFn(this, args);
|
||
|
for (const _resolve of resolveList) {
|
||
|
_resolve(promise);
|
||
|
}
|
||
|
resolveList = [];
|
||
|
}, wait);
|
||
|
if (shouldCallNow) {
|
||
|
leadingValue = applyFn(this, args);
|
||
|
resolve(leadingValue);
|
||
|
} else {
|
||
|
resolveList.push(resolve);
|
||
|
}
|
||
|
});
|
||
|
};
|
||
|
}
|
||
|
async function _applyPromised(fn, _this, args) {
|
||
|
return await fn.apply(_this, args);
|
||
|
}
|
||
|
|
||
|
exports.debounce = debounce;
|