Skip to content

Commit

Permalink
Fix double debounce trigger (#303)
Browse files Browse the repository at this point in the history
Co-authored-by: Victor Didenko <[email protected]>
  • Loading branch information
yumauri and victordidenko authored Nov 18, 2023
1 parent 19482f7 commit 9a9081a
Showing 1 changed file with 15 additions and 38 deletions.
53 changes: 15 additions & 38 deletions src/debounce/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,50 +43,27 @@ export function debounce<T>({

const $timeout = toStoreNumber(timeout);

const saveTimeoutId = createEvent<NodeJS.Timeout>();
const $timeoutId = createStore<NodeJS.Timeout | null>(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<T>) ?? 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<T[]>([], { serialize: 'ignore', skipVoid: false }).on(
Expand Down

0 comments on commit 9a9081a

Please sign in to comment.