All async
functions automatically return Promises. If you declare a function as async
, it will return a Promise, even if your only return
value is a simple value like a string or number. If you don't return explicitly, your async
function will still return a Promise with a value of undefined
.
In fact, it is more common for the body of an async
function to return a simple value rather than a promise; the assumption is that your function is async
because you await
the promises you consume within it. As a consequence, even if you return the value 5, the return value is a Promise (that resolves to 5) representing the potential delay that comes from any await
expressions in the function.
You don't have to return a Promise object explicitly in your async
function, and it is redundant to do so if you're just wrapping a simple value like 'resolved-value'
. Conversely, you can make a normal function behave like an async
function if you always return a Promise (potentially with Promise.resolve) and you never synchronously throw an error within it.
async function myFunction() {
makeSomeCall(); // Happens immediately.
await someOtherPromise(); // myFunction returns a Promise
// before someOtherPromise resolves; if it
// does without error, the returned Promise
return 5; // resolves to 5.
}
/** Behaves the same as the above function. */
function myFunctionButNotAsync() {
try {
makeSomeCall();
// If you didn't have someOtherPromise() to wait for here, then
// this is where Promise.resolve(5) would be useful to return.
return someOtherPromise().then(() => 5);
} catch (e) {
return Promise.reject(e);
}
}
All that said, you may have occasion to explicitly return a Promise object (such as one produced by Promise.all
or a separate Promise-returning function), which then observes rules similar to what Promise.resolve()
observes: If the object you return from an async
function is a Promise, or has a then
function, then the automatic Promise the async
function returns will wait for the specific Promise or Promise-like object you pass back with return
.
async function myFunction() {
makeSomeCall(); // Happens immediately.
await anythingElse(); // You can still await other things.
return someOtherPromise(); // The promise myFunction returns will take
// the same outcome as the Promise that
// someOtherPromise() returns.
}
In a related sense, this is why return await
is seen as redundant, though as described it does make a difference for the stack traces that you see if the wrapped promise is rejected.