Simplify Async Flow with Promise.withResolvers and Promise.try in JavaScript
This article explains how Promise.withResolvers and Promise.try streamline asynchronous control in JavaScript, providing clearer code for handling resolve/reject logic, event aggregation, and unified error handling with practical code examples.
Promise.withResolvers
In typical business code a Promise is used as a switch to control flow. The classic pattern looks like this:
let resolve;
const promise = new Promise((res, rej) => {
resolve = res;
});
promise.then(() => {
// do some thing
});
// Trigger resolve to run the then‑handler; resolve acts like a switch.
resolve();With Promise.withResolvers() the same logic becomes much simpler:
const { promise, resolve } = Promise.withResolvers();
promise.then(() => {
// do some thing
});
// Trigger resolve to run the then‑handler.
resolve(); Promise.withResolversis a static method that returns an object containing the promise, resolve, and reject functions, eliminating the need to create a new Promise manually.
Using it makes flow control more intuitive. For example, you can aggregate a fixed number of events and resolve or reject once the threshold is reached:
function eventHandler(eventsCount) {
const events = [];
const { promise, resolve, reject } = Promise.withResolvers();
return {
add: (event) => {
if (events.length < eventsCount) events.push(event);
if (events.length === eventsCount) resolve(events);
},
abort: () => reject("Events aggregation aborted."),
events: promise,
};
}
const eventsAggregator = eventHandler(3);
eventsAggregator.events
.then((events) => console.log("Resolved:", events))
.catch((reason) => console.error("Rejected:", reason));
eventsAggregator.add("event-one");
eventsAggregator.abort();
eventsAggregator.add("event-two");
eventsAggregator.add("event-three");
// Output: Rejected: Events aggregation aborted.In this example the Promise is used to control the number of events; once the count reaches the limit, resolve or reject ends the flow.
The method is supported in Chrome starting from version 119 (released 2023‑10‑31).
Promise.try
Promise.tryhas existed for a long time in libraries such as Bluebird, Q, and when. Its purpose is to provide a uniform handling mechanism for both synchronous and asynchronous operations.
Consider this example:
const f = () => console.log('now');
Promise.resolve().then(f);
console.log('next');
// Output: next nowAlthough f is a synchronous function, placing it in then defers its execution to the end of the current event loop, making it appear asynchronous. Promise.try lets you execute a function immediately while still returning a promise, so you can chain then and catch uniformly:
const f = () => console.log('now');
Promise.try(f);
console.log('next');Because Promise.try provides a consistent API, you can wrap both synchronous and asynchronous calls, enabling unified error handling:
Promise.try(() => database.users.get({ id: userId }))
.then(...)
.catch(...);In effect, Promise.try simulates a try block for promise chains, similar to how catch handles errors in a promise chain.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Code Mala Tang
Read source code together, write articles together, and enjoy spicy hot pot together.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
