Instead of mixing await
with .then()
, just await
each asynchronous function call directly in a try
block and deal with the error appropriately.
If the asynchronous function returns a rejected promise, await
will cause the rejection to throw from the try
block and be caught, skipping the rest of the control flow inside the try
.
const asyncFactory = label => async () => {
await new Promise(resolve => { setTimeout(resolve, 1000); });
if (Math.random() < 0.25) {
throw new Error(`${label} Error`);
}
console.log(`${label} Complete!`);
};
const somePromiseFunction = asyncFactory('somePromiseFunction');
const anotherPromiseFunction = asyncFactory('anotherPromiseFunction');
async function myFunction() {
try {
console.log('Start myFunction here');
await somePromiseFunction();
await anotherPromiseFunction();
} catch (error) {
console.log('Error caught:', error.message);
} finally {
console.log('End myFunction here');
}
}
myFunction();
You can actually achieve the equivalent without using async
and await
, and you don't need to nest your promises to do so:
const asyncFactory = label => () => {
return new Promise(resolve => {
setTimeout(resolve, 1000);
}).then(() => {
if (Math.random() < 0.25) {
throw new Error(`${label} Error`);
}
console.log(`${label} Complete!`);
});
};
const somePromiseFunction = asyncFactory('somePromiseFunction');
const anotherPromiseFunction = asyncFactory('anotherPromiseFunction');
const oneMorePromiseFunction = asyncFactory('oneMorePromiseFunction');
function myFunction() {
console.log('Start myFunction here');
return somePromiseFunction().then(() => {
return anotherPromiseFunction();
}).then(() => {
return oneMorePromiseFunction();
}).catch(error => {
console.log('Error caught:', error.message);
}).finally(() => {
console.log('End myFunction here');
});
}
myFunction();
Do note that Promise.prototype.finally()
is actually part of ECMAScript 2018, so if the browser supports it natively, it will also already support async
and await
. However, it can be polyfilled while async
and await
cannot.