seitu
Version:
70 lines (69 loc) • 1.63 kB
JavaScript
import { createReadableSubscription, createSubscription } from "../subscription/index.mjs";
//#region src/core/throttled/index.ts
/**
* Throttles updates from a source to at most once per `wait` ms (leading, then
* trailing). Unsubscribed `get()` reads through; subscribed `get()` returns the
* last emitted value.
*
* @example
* ```ts twoslash
* import { createStore, createThrottled } from 'seitu'
*
* const store = createStore('')
* const throttled = createThrottled(store, 300)
* throttled.subscribe(value => console.log('throttled:', value))
* ```
*/
function createThrottled(source, wait) {
let state = source.get();
let timeoutId;
let hasTrailing = false;
let active = false;
const cancel = () => {
clearTimeout(timeoutId);
timeoutId = void 0;
hasTrailing = false;
};
const { subscribe, notify } = createSubscription({ onFirstSubscribe() {
state = source.get();
active = true;
const unsubscribe = source.subscribe(() => {
if (timeoutId) {
hasTrailing = true;
return;
}
state = source.get();
notify();
timeoutId = setTimeout(() => {
timeoutId = void 0;
if (hasTrailing) {
hasTrailing = false;
state = source.get();
notify();
}
}, wait);
});
return () => {
cancel();
active = false;
unsubscribe();
};
} });
const flush = () => {
if (!hasTrailing) {
cancel();
return;
}
cancel();
state = source.get();
notify();
};
const get = () => active ? state : source.get();
return {
...createReadableSubscription(get, subscribe, notify, source.getServer),
cancel,
flush
};
}
//#endregion
export { createThrottled };