Skip to content

Latest commit

 

History

History
182 lines (134 loc) · 4.75 KB

promise.mdx

File metadata and controls

182 lines (134 loc) · 4.75 KB
titledescriptioncanonical
Promises
JS Promise handling in ReScript
/docs/manual/v11.0.0/promise

Promise

Note: Starting from ReScript 10.1 and above, we recommend using async / await when interacting with Promises.

promise type

Since 10.1

In ReScript, every JS promise is represented with the globally available promise<'a> type. For ReScript versions < 10.1, use its original alias Js.Promise.t<'a> instead.

Here's a usage example in a function signature:

// User.resi file type user = {name: string} let fetchUser: string => promise<user> 

To work with promise values (instead of using async / await) you may want to use the built-in Promise module.

Promise

A builtin module to create, chain and manipulate promises.

Creating a promise

letp1=Promise.make((resolve, reject) => { // We use uncurried functions for resolve / reject// for cleaner JS output without unintended curry callsresolve("hello world") }) letp2=Promise.resolve("some value") // You can only reject `exn` values for streamlined catch handlingexceptionMyOwnError(string) letp3=Promise.reject(MyOwnError("some rejection"))

Access the contents and transform a promise

letlogAsyncMessage= () => { openPromisePromise.resolve("hello world") ->then(msg=> { // then callbacks require the result to be resolved explicitlyresolve("Message: "++msg) }) ->then(msg=> { Console.log(msg) // Even if there is no result, we need to use resolve() to return a promiseresolve() }) ->ignore// Requires ignoring due to unhandled return value }

For comparison, the async / await version of the same code would look like this:

letlogAsyncMessage=async () => { letmsg=awaitPromise.resolve("hello world") Console.log(`Message: ${msg}`) }

Needless to say, the async / await version offers better ergonomics and less opportunities to run into type issues.

Handling Rejected Promises

You can handle a rejected promise using the Promise.catch() method, which allows you to catch and manage errors effectively.

Run multiple promises in parallel

In case you want to launch multiple promises in parallel, use Promise.all:

<CodeTab labels={["ReScript", "JS Output"]}>

@valexternalfetchMessage: string=>promise<string> ="global.fetchMessage"letlogAsyncMessage=async () => { letmessages=awaitPromise.all([fetchMessage("message1"), fetchMessage("message2")]) Console.log(messages->Array.joinWith(", ")) }
asyncfunctionlogAsyncMessage(param){varmessages=awaitPromise.all([global.fetchMessage("message1"),global.fetchMessage("message2")]);console.log(messages.join(", "));}export{logAsyncMessage,}

Js.Promise module (legacy - do not use)

Note: The Js.Promise bindings are following the outdated data-last convention from a few years ago. We kept those APIs for backwards compatibility. Either use Promise or a third-party promise binding instead.

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.

Usage

Using the pipe operator:

<CodeTab labels={["ReScript", "JS Output"]}>

letmyPromise=Js.Promise.make((~resolve, ~reject) =>resolve(. 2)) myPromise->Js.Promise.then_(value=> { Console.log(value) Js.Promise.resolve(value+2) }, _)->Js.Promise.then_(value=> { Console.log(value) Js.Promise.resolve(value+3) }, _)->Js.Promise.catch(err=> { Console.log2("Failure!!", err) Js.Promise.resolve(-2) }, _)
varmyPromise=newPromise(function(resolve,reject){returnresolve(2);});myPromise.then(function(value){console.log(value);returnPromise.resolve((value+2)|0);}).then(function(value){console.log(value);returnPromise.resolve((value+3)|0);}).catch(function(err){console.log("Failure!!",err);returnPromise.resolve(-2);});
close