seitu
Version:
54 lines (53 loc) • 1.35 kB
JavaScript
import { createReadableSubscription, createSubscription } from "../subscription/index.mjs";
//#region src/core/throttled-fn/index.ts
/**
* Throttled callable that is also a subscribable. First call fires immediately;
* later calls within `wait` batch into one trailing call.
*
* @example
* ```ts twoslash
* import { createThrottledFn } from 'seitu'
*
* const log = createThrottledFn((msg: string) => console.log(msg), 300)
* log.subscribe(result => console.log('result:', result))
* log('hello') // fires immediately
* log('world') // throttled — fires after 300ms
* log.get()
* log.flush()
* ```
*/
function createThrottledFn(fn, wait) {
let state;
let timeoutId;
let trailingArgs;
const { subscribe, notify } = createSubscription();
const get = () => state;
const cancel = () => {
clearTimeout(timeoutId);
timeoutId = void 0;
trailingArgs = void 0;
};
const invoke = (args) => {
state = fn(...args);
notify();
};
const flush = () => {
const args = trailingArgs;
cancel();
if (args) invoke(args);
};
return Object.assign((...args) => {
if (timeoutId) {
trailingArgs = args;
return;
}
invoke(args);
timeoutId = setTimeout(flush, wait);
}, createReadableSubscription(get, subscribe, notify), {
cancel,
flush,
pending: () => trailingArgs !== void 0
});
}
//#endregion
export { createThrottledFn };