Skip to content

Ability to pass an AbortSignal to Bun.sleep #17866

Open
@iitzkube

Description

@iitzkube

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions