Docs / Language Manual / Promise

Async & Promise

ReScript's primary mechanism for async programming is the same as JavaScript's (callbacks and promises), since we compile cleanly to JavaScript and would like to avoid dragging in a heavy custom runtime.

However, it is planned for us to introduce a coroutine-like feature in the future; for that reason, we're postponing introducing the keywords async and await into the language; though our (upcoming) Promise API bindings revamp + pipe will make your async code already look better than otherwise.


ReScript has built-in support for JavaScript promises. The 3 functions you generally need are:

  • Js.Promise.resolve: 'a => Js.Promise.t('a)

  • Js.Promise.then_: ('a => Js.Promise.t('b), Js.Promise.t('a)) => Js.Promise.t('b)

  • Js.Promise.catch: (Js.Promise.error => Js.Promise.t('a), Js.Promise.t('a)) => Js.Promise.t('a)

Additionally, here's the type signature for creating a promise on the ReScript side:

Js.Promise.make: ( ( ~resolve: (. 'a) => unit, ~reject: (. exn) => unit ) => unit ) => Js.Promise.t<'a>

This type signature means that make takes a callback that takes 2 named arguments, resolve and reject. Both arguments are themselves uncurried callbacks (with a dot). make returns the created promise.


Using the pipe operator:

ReScriptJS Output
let myPromise = Js.Promise.make((~resolve, ~reject) => resolve(. 2))

|> Js.Promise.then_(value => {
     Js.Promise.resolve(value + 2)
|> Js.Promise.then_(value => {
     Js.Promise.resolve(value + 3)
|> Js.Promise.catch(err => {
     Js.log2("Failure!!", err)

Tips & Tricks

Promises aren't the best abstractions, especially in JavaScript. When used inside React or ReasonReact, it is almost always wrong.

For that reason, we actually recommend judicious usages of callback-based apis, like so.

This applies to other leaky, slow and uncancellable, and colored promise abstractions like fetch. Prefer using them only for interop, not for your core logic.