From 37e820b595b2b917a1ffc552ce4f3adc8d112913 Mon Sep 17 00:00:00 2001 From: Victor Didenko Date: Sat, 18 Nov 2023 15:00:10 +0300 Subject: [PATCH] Fix double debounce trigger --- src/debounce/index.ts | 53 ++++++++++++------------------------------- 1 file changed, 15 insertions(+), 38 deletions(-) diff --git a/src/debounce/index.ts b/src/debounce/index.ts index 66aee473..b56ad775 100644 --- a/src/debounce/index.ts +++ b/src/debounce/index.ts @@ -43,50 +43,27 @@ export function debounce({ const $timeout = toStoreNumber(timeout); - const saveTimeoutId = createEvent(); - const $timeoutId = createStore(null, { - serialize: 'ignore', - }).on(saveTimeoutId, (_, id) => id); - const saveReject = createEvent<() => void>(); - // eslint-disable-next-line @typescript-eslint/no-empty-function - const $rejecter = createStore<(() => void) | null>(null, { - serialize: 'ignore', - }).on(saveReject, (_, rj) => rj); + const saveCancel = createEvent<[NodeJS.Timeout, () => void]>(); + const $canceller = createStore<[NodeJS.Timeout, () => void] | []>([], { serialize: 'ignore' }) + .on(saveCancel, (_, payload) => payload) const tick = (target as UnitTargetable) ?? createEvent(); - const timerBaseFx = createEffect< - { - timeout: number; - rejectPromise: (() => void) | null; - timeoutId: NodeJS.Timeout | null; - }, - void - >(({ timeout, timeoutId, rejectPromise }) => { - if (timeoutId) clearTimeout(timeoutId); - if (rejectPromise) rejectPromise(); - return new Promise((resolve, reject) => { - saveReject(reject); - saveTimeoutId(setTimeout(resolve, timeout)); - }); - }); const timerFx = attach({ name: name || `debounce(${(source as any)?.shortName || source.kind}) effect`, - source: { - timeoutId: $timeoutId, - rejectPromise: $rejecter, - }, - mapParams: (timeout: number, { timeoutId, rejectPromise }) => { - return { - timeout, - timeoutId, - rejectPromise, - }; - }, - effect: timerBaseFx, + source: $canceller, + effect([ timeoutId, rejectPromise ], timeout: number) { + if (timeoutId) clearTimeout(timeoutId); + if (rejectPromise) rejectPromise(); + return new Promise((resolve, reject) => { + saveCancel([ + setTimeout(resolve, timeout), + reject + ]) + }); + } }); - $rejecter.reset(timerFx.done); - $timeoutId.reset(timerFx.done); + $canceller.reset(timerFx.done); // It's ok - nothing will ever start unless source is triggered const $payload = createStore([], { serialize: 'ignore', skipVoid: false }).on(