Difference Between 'Return Await Promise' and 'Return Promise'

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



Leave a reply



Submit