Using await within a Promise
You can also chain the promises yourself by simply doing this:
return new Promise((resolve, reject) => {
somethingAsynchronous().then((value) => {
if (value === something) {
return resolve('It worked!');
} else {
return reject('Nope. Try again.');
}
}, (error) => { reject(error); });
});
I've been using this for some time and it works perfectly for me.
You do this:
async function outerFunction() {
const value = await somethingAsynchronous();
if (value === something) {
return 'It Worked!';
}
throw Error('Nope. Try again.');
}
Using async
wraps the result of outerFunction
with a Promise.
If you want that wrapping promise to resolve to something, just return it from the async
function. If you want the wrapping promise to be rejected, throw an error inside the async
function.
But then how do you account for code such as this?
async function outerFunction() {
if (someSynchronousCheck()) {
throw Error('Nope. Try again.');
}
const value = await somethingAsynchronous();
// ...
}
new Promise(async (resolve, reject) => { ... })
is relatively new antipattern. It results in creating 2 promise objects instead of 1, uncaught errors that happen inside constructor cannot be caught with try..catch
and result in unhandled rejection.
Considering that promise asynchronous code can be handled with async..await
, current use case for Promise
constructor is non-promise asynchronous code, e.g.:
new Promise(resolve => setTimeout(resolve, 1000))
When Promise
constructor contains synchronous code or involves other promises, a promise should be constructed with async
function. A drop-in replacement is async
IIFE:
return (async (resolve, reject) => {
const value = await somethingAsynchronous();
if (value === something) {
return 'It worked!';
} else {
throw 'Nope. Try again.';
}
})();
If the need for Promise
constructor still presents when being used together with async
, Promise
constructor should be moved down in hierarchy so it won't wrap any async
function.
My final question is, why is the callback passed to a Promise not inherently async? It is already wrapped within a promise and expects the resolve/reject functions to be called asynchronously.
async
function isn't just a function that is executed asynchronously, it returns another promise that is supposed to be utilized - or at least handled with catch
. Promise
isn't supposed to utilize a promise that is returned from constructing function.
The constructor can resolve on same tick and doesn't necessarily have to be asynchronous.
Promise.resolve(1);
is similar to
Promise(resolve => resolve(1))
and not to
Promise(resolve => setTimeout(() => resolve(1)))