Promise.try to improve error handling and sync/async interoperability
source link: https://pawelgrzybek.com/promise-try-to-improve-error-handling-and-sync-async-interoperability/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Promise.try to improve error handling and sync/async interoperability
Published: 2024.04.09 · 3 minutes read
A few months ago, I published “Deferred JavaScript promises using Promise.withResolvers
”, which explains a modern way of dealing with one of the cumbersome chores as old as the Promises in JavaScript. Following the trend of adding to the specifications features that simplify our programs, today is about the upcoming Promise.try
, which is quickly progressing through the ECMAScript proposals stages.
Assuming we have two functions, one that returns a promise and another one that synchronously returns a value, we can mix and match them like so:
const retSync = () => "sync return";
const retAsync = () => new Promise((r) => r("async return"));
(async () =>
retAsync()
.then(console.log)
.then(retSync)
.then(console.log)
.catch(console.error))();
// async return
// sync return
Let’s flip the order and put a synchronous function first.
// 🚨 this is not going to work
const retSync = () => "sync return";
const retAsync = () => new Promise((r) => r("async return"));
(async () =>
retSync()
.then(console.log)
.then(retAsync)
.then(console.log)
.catch(console.error))();
// TypeError: retSync().then is not a function. (In 'retSync().then(console.log)', 'retSync().then' is undefined)
We can’t do that because the return value of retSync
is not a thenable promise. We need to wrap a synchronously returning function in a promise.
const retSync = () => "sync return";
const retAsync = () => new Promise((r) => r("async return"));
(async () =>
Promise.resolve()
.then(retSync)
.then(console.log)
.then(retAsync)
.then(console.log)
.catch(console.error))();
// sync return
// async return
That works, but we wasted an event-loop cycle. It’s doable to solve, though!
const retSync = () => "sync return";
const retAsync = () => new Promise((r) => r("async return"));
(async () =>
new Promise((resolve) => resolve(retSync()))
.then(console.log)
.then(retAsync)
.then(console.log)
.catch(console.error))();
// sync return
// async return
Finally, but isn’t that tiresome? It would be cool to mix and match them without being concerned about whether a thing is synchronous or asynchronous. Also, a common catch
clause is handy for handling errors in a single place, without writing error handling individually for sync and async executions.
There are plenty of solutions in the ecosystem already: p-try
by Sindre Sorhus, Bluebird Promise.try
/Promise.attempt
or es6-promise-try
, to name a few. Also, there is a native Promise.try
progressing through the ECMAScript proposal stages, and I am sure it will be part of a language specification soon.
const retSync = () => "sync return";
const retAsync = () => new Promise((r) => r("async return"));
(async () =>
Promise.try(retSync)
.then(console.log)
.then(retAsync)
.then(console.log)
.catch(console.error))();
// sync return
// async return
Hopefully, this post helped you to understand the purpose and what kind of problem Promise.try
is trying to solve. Keep on coding and I will catch("you")
next time 👋
Did you like it? Please share it with your friends. Thanks!
Leave a comment#
👆 you can use Markdown here
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK