Promise.withResolvers() - resolve your promises from outside!

Promise.withResolvers() - resolve your promises from outside!

26 Jun 2024 ecma-2024 promises

Promises are awesome. When they were introduced some years ago, they revolutionised how developers could handle asynchronous operations. Before they came along, you either had ugly code or used something like jQuery's (awesome) deferred objects.

One issue I and other developers had with them was that there was no built-in way to resolve (i.e. fulfill or reject) promises from outside the promise's own callback. In this regard, they contrasted (badly) with jQuery deferreds.

//native promises const prom = new Promise(res => { //I can resolve it only from in here }); //jQuery deferred const dfd = new $.Deferred; dfd.resolve(); //<-- I can resolve from anywhere

It's possible to circumvent this issue by declaring placeholders for your resolvers outside the function, then overwriting them from within the promise callback, like so:

let outerRes, outerRej; const prom = new Promise((res, rej) => { outerRes = res; outerRej = rej; }); outerRes(); //<-- now we can resolve from outside :)

The revolutionary async/await combo (still the best thing to happen to JavaScript in the last 10 years) made things easier still, by flattening code, i.e. not requiring us to operate within nested callbacks.

ANYWAY, so much for the back story. Now, in ECMAScript 2024, we're given a new static method to play with, Promise.withResolvers().

Its name doesn't give too much away, but it's actually super helpful. It allows you to create a promise, just as you normally would via the promise constructor, but it gives you outside access to the resolver methods.

It does this by returning the three parts of the promise, in an object - the promise itself, the fulfill resolver, and the reject resolver.

const { promise, resolve, reject } = Promise.withResolvers()

Suddenly our promise doesn't need a callback at all. We can still use it like a normal promise - i.e. await its resolution state, though. Also note that we don't instantiate this new method the way we would with the promise constructor.

Let's finish up with an example:

lconst { promise, resolve, reject } = Promise.withResolvers(); setTimeout(() => resolve(15), 2000); const num = await promise; alert(num); //15

Did I help you? Feel free to be amazing and buy me a coffee on Ko-fi!