@nesvet/n
Version:
Various utilities
102 lines • 3.13 kB
JavaScript
import { noop } from "./noop.js";
export function debounce(callback, limit = 0, options = {}) {
let { leading = false, trailing = true } = options;
const { maxWait = Infinity } = options;
let timeout;
let maxWaitTimeout;
let end;
let context;
let args;
let initial;
let final;
let result;
const expired = async () => {
const n = Date.now();
if (n >= end) {
timeout = undefined;
end = undefined;
clearTimeout(maxWaitTimeout);
if (typeof final == "function")
await final();
debounced.resolve(result);
debounced.promise.isResolved = true;
initial = leading;
}
else {
clearTimeout(timeout);
timeout = setTimeout(expired, end - n);
}
};
const maxWaitExpired = Number.isFinite(maxWait) ? () => {
if (final === run)
final = false;
run();
maxWaitTimeout = setTimeout(maxWaitExpired, maxWait);
} : null;
async function run() {
return (result = await callback.apply(context, args));
}
if (leading && typeof leading == "boolean")
leading = run;
initial = leading;
if (trailing && typeof trailing == "boolean")
trailing = run;
final = trailing;
const debounced = Object.assign(function (..._args) {
args = _args;
context = this; // eslint-disable-line no-invalid-this
end = Date.now() + limit;
final = trailing;
if (debounced.promise.isResolved)
debounced.promise = Object.assign(new Promise(resolve => {
debounced.resolve = resolve;
if (typeof initial == "function") {
initial();
initial = false;
if (final === run)
final = false;
}
if (!timeout) {
timeout = setTimeout(expired, limit);
if (maxWaitExpired)
maxWaitTimeout = setTimeout(maxWaitExpired, maxWait);
}
}), {
isResolved: false
});
return debounced.promise;
}, {
callback,
promise: Object.assign(Promise.resolve(), {
isResolved: true
}),
resolve: noop,
run,
clear: async (shouldRun) => {
clearTimeout(timeout);
timeout = undefined;
clearTimeout(maxWaitTimeout);
debounced.promise.isResolved = true;
debounced.resolve(shouldRun ? await run() : result);
}
});
return debounced;
}
debounce.noop = Object.assign(() => { }, {
callback: noop,
promise: Object.assign(Promise.resolve(), {
isResolved: true
}),
resolve: noop,
run: noop,
clear: noop
});
export function throttle(callback, limit, options) {
return debounce(callback, limit, {
maxWait: limit,
leading: true,
trailing: true,
...options
});
}
//# sourceMappingURL=debounce.js.map