Telegram Web K with changes to work inside I2P https://web.telegram.i2p/
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.
 
 
 
 
 

78 lines
2.2 KiB

// * Jolly Cobra's schedulers
import ctx from '../../environment/ctx';
import {AnyFunction, Awaited} from '../../types';
import noop from '../noop';
export type DebounceReturnType<F extends AnyFunction> = {
(...args: Parameters<F>): Promise<Awaited<ReturnType<F>>>;
clearTimeout(): void;
isDebounced(): boolean;
};
export default function debounce<F extends AnyFunction>(
fn: F,
ms: number,
shouldRunFirst = true,
shouldRunLast = true
): DebounceReturnType<F> {
let waitingTimeout: number;
let waitingPromise: Promise<Awaited<ReturnType<F>>>, resolve: (result: any) => void, reject: () => void;
let hadNewCall = false;
const invoke = (args: Parameters<F>) => {
const _resolve = resolve, _reject = reject;
try {
const result = fn.apply(null, args);
_resolve(result);
} catch(err) {
console.error('debounce error', err);
// @ts-ignore
_reject(err);
}
};
const debounce = (...args: Parameters<F>) => {
if(!waitingPromise) waitingPromise = new Promise((_resolve, _reject) => (resolve = _resolve, reject = _reject));
if(waitingTimeout) {
clearTimeout(waitingTimeout);
hadNewCall = true;
reject();
waitingPromise = new Promise((_resolve, _reject) => (resolve = _resolve, reject = _reject));
} else if(shouldRunFirst) {
invoke(args);
hadNewCall = false;
}
const _waitingTimeout = ctx.setTimeout(() => {
// will run if should run last or first but with new call
if(shouldRunLast && (!shouldRunFirst || hadNewCall)) {
invoke(args);
}
// if debounce was called during invoking
if(waitingTimeout === _waitingTimeout) {
waitingTimeout = waitingPromise = resolve = reject = undefined;
hadNewCall = false;
}
}, ms);
waitingTimeout = _waitingTimeout;
waitingPromise.catch(noop);
return waitingPromise;
};
debounce.clearTimeout = () => {
if(waitingTimeout) {
ctx.clearTimeout(waitingTimeout);
reject();
waitingTimeout = waitingPromise = resolve = reject = undefined;
hadNewCall = false;
}
};
debounce.isDebounced = () => !!waitingTimeout;
return debounce;
}