Description
What is the problem this feature would solve?
The Bun.sleep()
method is really handy. I think it would be even better if it supported AbortSignals.
There's a lot of cases when it's crucial to stop the timer immediately and this isn't possible with Bun.sleep
. I have a custom cancelable sleep utility in my codebase but it'd be nice if I didn't have to – the global Bun.sleep()
is a lot nicer 😄
What is the feature you are proposing to solve the problem?
Proposed API change:
Allow passing an AbortSignal
to the Bun's sleep
/sleepAsync
methods to make them "cancelable".
This will not be a breaking change.
Now, whether it should throw or not when the signal is aborted, I think ideally it should, but an argument can still be made that a quiet return could be preferable in scenarios where aborts are an expected part of the normal flow, reducing the need for excessive error-handling boilerplate and treating cancellation as a valid outcome rather than an exception.
API proposal:
- Passing an options argument:
options: { signal: AbortSignal; throwOnAbort?: boolean }
- Allow user to control the throwing behavior.
- function sleep(ms: number | Date): Promise<void>;
+ function sleep(ms: number | Date, options?: { signal?: AbortSignal, throwOnAbort?: boolean }): Promise<void>;
- function sleepSync(ms: number | Date): Promise<void>;
+ function sleepSync(ms: number | Date, options?: { signal?: AbortSignal, throwOnAbort?: boolean }): void;
Full implementation draft specified below
Alternative API proposal:
- Passing an options argument:
options?: { signal?: AbortSignal }
. - Similar API to fetch, addEventListener, ReadableStream.pipeTo, etc.
sleep
will always throws on signal's abort.
- function sleep(ms: number | Date): Promise<void>;
+ function sleep(ms: number | Date, options?: { signal?: AbortSignal }): Promise<void>;
- function sleepSync(ms: number | Date): Promise<void>;
+ function sleepSync(ms: number | Date, options?: { signal?: AbortSignal }): void;
Always throwing on abort is also consistent with other built-in APIs. The { throwOnAbort: false }
behavior from above could be achieved with a simple .catch()
:
await sleep(1000, { signal }).catch(() => {})
What alternatives have you considered?
Custom sleep utility