diff --git a/packages/utils/src/scheduleAction.ts b/packages/utils/src/scheduleAction.ts index bc874302da..ff03b14cc4 100644 --- a/packages/utils/src/scheduleAction.ts +++ b/packages/utils/src/scheduleAction.ts @@ -27,27 +27,38 @@ const resolveAfterMs = (ms: number | undefined, clear: AbortSignal) => new Promise((resolve, reject) => { if (clear.aborted) return reject(); if (ms === undefined) return resolve(); - const timeout = setTimeout(resolve, ms); + let timeout: ReturnType; const onClear = () => { clearTimeout(timeout); clear.removeEventListener('abort', onClear); reject(); }; + timeout = setTimeout(() => { + clear.removeEventListener('abort', onClear); + resolve(); + }, ms); clear.addEventListener('abort', onClear); }); -const rejectAfterMs = (ms: number | undefined, reason: () => Error, clear: AbortSignal) => +const rejectAfterMs = (ms: number, reason: () => Error, clear: AbortSignal) => new Promise((_, reject) => { if (clear.aborted) return reject(); - const timeout = ms !== undefined ? setTimeout(() => reject(reason()), ms) : undefined; + let timeout: ReturnType | undefined; const onClear = () => { clearTimeout(timeout); clear.removeEventListener('abort', onClear); reject(); }; + timeout = setTimeout(() => { + clear.removeEventListener('abort', onClear); + reject(reason()); + }, ms); clear.addEventListener('abort', onClear); }); +const maybeRejectAfterMs = (ms: number | undefined, reason: () => Error, clear: AbortSignal) => + ms === undefined ? [] : [rejectAfterMs(ms, reason, clear)]; + const rejectWhenAborted = (signal: AbortSignal | undefined, clear: AbortSignal) => new Promise((_, reject) => { if (clear.aborted) return reject(); @@ -118,13 +129,17 @@ export const scheduleAction = async ( try { return await Promise.race([ rejectWhenAborted(signal, clear), - rejectAfterMs(deadlineMs, abortedByDeadline, clear), + ...maybeRejectAfterMs(deadlineMs, abortedByDeadline, clear), resolveAfterMs(delay, clear).then(() => attemptLoop( attemptCount, (attempt, abort) => Promise.race([ - rejectAfterMs(getParams(attempt).timeout, abortedByTimeout, clear), + ...maybeRejectAfterMs( + getParams(attempt).timeout, + abortedByTimeout, + clear, + ), resolveAction(action, abort), ]), (attempt, error) => {