Promise helper name

Hi folks, I would like to add helper function to the standard library for Promises:

module Promise = {
    let xyz = ms => Promise.make((resolve, _) => setTimeout(resolve, ms)->ignore)
}

Usage:

let bar = async () => {
   await Promise.xyz(1000)
   42
}

What would you call xyz?
Please upvote any previous answer you agree on instead of posting it again.

1 Like

wait (adding characters to reach minimum)

3 Likes

I have a PromiseUtils.delay in multiple codebases.

2 Likes

What about the obvious sleep ?

2 Likes

definitely sleep. what i would ask you to do however is make it cancelable:

from one of our internal projects:

/***
Async helpers.

Utilities for timeouts, cancelable sleeps, and racing promises against a timeout.
Useful for bounding async work and composing promise-based control flow.
*/

/**
A promise that can be canceled.

- `promise`: resolves to `Some(value)` on success, or `None` if canceled/timeout fires first
- `cancel`: immediately resolves `promise` with `None`
*/
type cancelablePromise<'a> = {
  promise: promise<option<'a>>,
  // Immediately resolves the promise with None
  cancel: unit => unit,
}

/**
Create a cancelable sleep.

- `ms`: delay in milliseconds
- Returns a `{promise, cancel}` where:
  - `promise` resolves to `Some(())` after `ms`
  - calling `cancel()` resolves it early with `None`
*/
let sleepCancelable = (~ms: int): cancelablePromise<unit> => {
  let resolveMut = ref(_ => ())
  let timeoutMut = ref(None)

  let p = Promise.make((resolve, _) => {
    resolveMut := resolve

    let cb = () => {
      resolveMut.contents(Some())
      resolveMut := (_ => ())
      timeoutMut := None
    }
    timeoutMut := Some(setTimeout(cb, ms))
  })

  let cancel = () => {
    switch timeoutMut.contents {
    | Some(id) =>
      clearTimeout(id)
      resolveMut.contents(None)
      resolveMut := (_ => ())
      timeoutMut := None
    | None => ()
    }
  }

  {promise: p, cancel}
}

/**
Sleep for `ms` milliseconds.

Resolves when the delay elapses. Non-cancelable convenience wrapper around `sleepCancelable`.
*/
let sleep = (~ms) => sleepCancelable(~ms).promise->Promise.thenResolve(_ => ())

anyway, sleep has been the name for this type of functionality for decades (takes me back to the good old days of win32 api), and if you put it under Promise, it’s obvious it’s async.

1 Like

Yeah, another thought I had was to pass an AbortSignal.

Might make sense to have two helpers really.

1 Like

It might be worth noting that Node has a promise version of setTimeout that can be given an AbortSignal.

I’ve called the Node version setTimeoutAsync and the promise+setTimeout version wait in my ReScript code.

I think something like wait or delay is better than sleep since sleep is normally a blocking operation in languages like Bash or C. For me, “wait” has a more asynchronous meaning.

3 Likes