Difference between `return await promise` and `return promise`
Most of the time, there is no observable difference between return
and return await
. Both versions of delay1Second
have the exact same observable behavior (but depending on the implementation, the return await
version might use slightly more memory because an intermediate Promise
object might be created).
However, as @PitaJ pointed out, there is one case where there is a difference: if the return
or return await
is nested in a try
-catch
block. Consider this example
async function rejectionWithReturnAwait () {
try {
return await Promise.reject(new Error())
} catch (e) {
return 'Saved!'
}
}
async function rejectionWithReturn () {
try {
return Promise.reject(new Error())
} catch (e) {
return 'Saved!'
}
}
In the first version, the async function awaits the rejected promise before returning its result, which causes the rejection to be turned into an exception and the catch
clause to be reached; the function will thus return a promise resolving to the string "Saved!".
The second version of the function, however, does return the rejected promise directly without awaiting it within the async function, which means that the catch
case is not called and the caller gets the rejection instead.
Does return await makes any difference?
It is redundant.
It extracts the value from the promise returned by bar, and then resolves the promise returned by foo
with it.
If you return bar
's promise directly, then the promise returned by foo
adopts it to the same effect.
Promise.all vs [await x, await y] - Is it really the same?
No, you should not accept that:
return [await someFunction1(), await someFunction2()];
Is the same as:
return await Promise.all([someFunction1(), someFunction2()]);
I should also note that await
in the above return await
is not needed. Check out this blog post to learn more.
They are different!
The first approach (sequential)
Let's determine the difference by inspecting how each of the two alternatives works.
[await someFunction1(), await someFunction2()];
Here, in an async
context, we create an array literal. Note that someFunction1
is called (a function which probably returns a new promise each time it gets called).
So, when you call someFunction1
, a new promise is returned, which then "locks" the async
context because the preceding await
.
In a nutshell, the await someFunction1()
"blocks" the array initialization until the returned promise gets settled (by getting resolved or rejected).
The same process is repeated to someFunction2
.
Note that, in this first approach, the two promises are awaited in sequence. There is, therefore, no similarity with the approach that uses Promise.all
. Let's see why.
The second approach (non-sequential)
Promise.all([someFunction1(), someFunction2()])
When you apply Promise.all
, it expects an iterable of promises. It waits for all the promises you give to resolve before returns a new array of resolved values, but don't wait each promise resolve until waiting another one. In essence, it awaits all the promises at the same time, so it is a kind of "non-sequential". As JavaScript is single-threaded, you cannot tell this "parallel", but is very similar in the behavior point of view.
So, when you pass this array:
[someFunction1(), someFunction2()]
You are actually passing an array of promises (which are returned from the functions). Something like:
[Promise<...>, Promise<...>]
Note that the promises are being created outside Promise.all
.
So you are, in fact, passing an array of promises to Promise.all
. When both of them gets resolved, the Promise.all
returns the array of resolved values. I won't explain in all details how Promise.all
works, for that, I suggest you checking out the documentation.
You can replicate this "non-sequential" approach by creating the promises before using the await
. Like so:
const promise1 = someFunction1();
const promise2 = someFunction2();
return [await promise1, await promise2];
While promise1
is being waited, promise2
is already running (as it was created before the first await
), so the behavior is similar to Promise.all
's.
async/await implicitly returns promise?
The return value will always be a promise. If you don't explicitly return a promise, the value you return will automatically be wrapped in a promise.
async function increment(num) {
return num + 1;
}
// Even though you returned a number, the value is
// automatically wrapped in a promise, so we call
// `then` on it to access the returned value.
//
// Logs: 4
increment(3).then(num => console.log(num));
Same thing even if there's no return! (Promise { undefined }
is returned)
async function increment(num) {}
Same thing even if there's an await
.
function defer(callback) {
return new Promise(function(resolve) {
setTimeout(function() {
resolve(callback());
}, 1000);
});
}
async function incrementTwice(num) {
const numPlus1 = await defer(() => num + 1);
return numPlus1 + 1;
}
// Logs: 5
incrementTwice(3).then(num => console.log(num));
Promises auto-unwrap, so if you do return a promise for a value from within an async
function, you will receive a promise for the value (not a promise for a promise for the value).
function defer(callback) {
return new Promise(function(resolve) {
setTimeout(function() {
resolve(callback());
}, 1000);
});
}
async function increment(num) {
// It doesn't matter whether you put an `await` here.
return defer(() => num + 1);
}
// Logs: 4
increment(3).then(num => console.log(num));
In my synopsis the behavior is indeed inconsistent with traditional
return statements. It appears that when you explicitly return a
non-promise value from an async function, it will force wrap it in a
promise. I don't have a big problem with it, but it does defy normal
JS.
ES6 has functions which don't return exactly the same value as the return
. These functions are called generators.
function* foo() {
return 'test';
}
// Logs an object.
console.log(foo());
// Logs 'test'.
console.log(foo().next().value);
What is the difference between consume the result from await and return the result from await?
What made the first code snippet return
Both code snippets return at the same point. The await
keyword, when it gets a promise on the RHS, makes the function it belongs to go to sleep until that promise settles.
Meanwhile, the calling function gets the promise returned by f
and continues running.
That's the point of using async
functions: They don't block when they are dealing with something asynchronous.
Related Topics
Case Insensitive Regex in JavaScript
Why Do We Use Spreadsheetapp.Flush();
How to Check for an Undefined or Null Variable in JavaScript
Center a Popup Window on Screen
Handling Errors in Promise.All
How to Compare Software Version Number Using JS? (Only Number)
Can You Get a Users Local Lan Ip Address via JavaScript
How to Escape a JSON String Containing Newline Characters Using JavaScript
How to Hide JavaScript Code in a Webpage
Number Prime Test in JavaScript
How to Get a Dom Element from a Jquery Selector
Call a JavaScript Function at a Specific Time of Day
Calling an Asynchronous Function Within a for Loop in JavaScript
Multiple Assignment in JavaScript? What Does [A,B,C] = [1, 2, 3]; Mean
Call Static Methods from Regular Es6 Class Methods