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.
|
|
//#region src/index.tsconst DEBOUNCE_DEFAULTS = { trailing: true };/**Debounce functions@param fn - Promise-returning/async function to debounce.@param wait - Milliseconds to wait before calling `fn`. Default value is 25ms@returns A function that delays calling `fn` until after `wait` milliseconds have elapsed since the last time it was called.@example```import { debounce } from 'perfect-debounce';const expensiveCall = async input => input;const debouncedFn = debounce(expensiveCall, 200);for (const number of [1, 2, 3]) {console.log(await debouncedFn(number));}//=> 1//=> 2//=> 3```*/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; }; const debounced = function(...args) { if (options.trailing) trailingArgs = args; if (currentPromise) 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); trailingArgs = null; for (const _resolve of resolveList) _resolve(promise); resolveList = []; }, wait); if (shouldCallNow) { leadingValue = applyFn(this, args); resolve(leadingValue); } else resolveList.push(resolve); }); }; const _clearTimeout = (timer) => { if (timer) { clearTimeout(timer); timeout = null; } }; debounced.isPending = () => !!timeout; debounced.cancel = () => { _clearTimeout(timeout); resolveList = []; trailingArgs = null; }; debounced.flush = () => { _clearTimeout(timeout); if (!trailingArgs || currentPromise) return; const args = trailingArgs; trailingArgs = null; return applyFn(this, args); }; return debounced;}async function _applyPromised(fn, _this, args) { return await fn.apply(_this, args);}
//#endregionexport { debounce };
|