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.
59 lines
1.5 KiB
59 lines
1.5 KiB
'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;
|
|
|