Y
In short, the return is different from return await when inside a block try.In the specific case of the question, there is no difference. There, return is the same as return await because it is out of a block try (which is where the difference happens).However, there are some cases where there may be a difference. Most of the time, it's the same thing. However, it is important to know when return and return await are different since the behavior of the code can be slightly changed.What is async?When you mark a function as async, she always will return one Promise. In case an error is released within this asynchronous function, the returned promise will be the type rejected. Otherwise, it will be solved with some value. If you do not use a return explicitly, a value-solved promise will be returned undefined.Overall, it is ideal to use asynchronous functions only when you use one await explicit within them. Otherwise, the code may end up being counterintuitive for some who do not know exactly the behavior of asynchronous functions.If you just want return a promise (as in the question code), it is not necessary to use async or await, since there is no real need to wait the conclusion of the promise.The operator awaitThe operator await can only be used within functions marked asynchronous. He basically Wait by the conclusion of the promise passed to him:If the promise is resolved, it will "pack" the value of within Promise, which will be the value returned by the expression.If the promise is rejected, it will cast the error, which can be captured in blocks try/catch.From that second item in the list above, it is possible to infer the difference between return and return await.Returning a promise — return <promise>Consider the example below, where we have an asynchronous function foo that calls a function waitAndMaybeReject, which returns a promise that can be resolved with any value or reject with any error.async function foo() {
try {
// ↓↓↓↓↓↓
return waitAndMaybeReject();
}
catch (e) {
return 'caught';
}
}
The function waitAndMaybeReject returns a promise. However, foo does not really wait for the conclusion of this promise. The function foo simply returns (immediately) Promise returned by the application waitAndMaybeReject. In this case, a "delegation" of the promise occurs.How the promise was returned before it is, in fact, resolved or rejected, one can state that the try/catch is useless there, because even if waitAndMaybeReject reject with some mistake, the catch will not be able to capture it, since the promise has already been returned to those who called foo.Returning the value of a completed promise — return await <promise>Now consider this code (still with the same function waitAndMaybeReject of the previous example):async function foo() {
try {
// ↓↓↓↓↓↓ ↓↓↓↓↓
return await waitAndMaybeReject();
}
catch (e) {
return 'caught';
}
}
Note now that, as the operator used await, we are indeed awaiting the conclusion of the promise returned by waitAndMaybeReject. Thus, in the case of the promise returned by waitAndMaybeReject is rejected, the block catch will be able to capture the exception.The promise, with the return await was not delegated by foo to his caller. On the contrary: the promise was awaited by foo and its value solved (or rejection) were properly handled by foo.Note that now foo returns the value solved by the promise waitAndMaybeReject Return, OR "caught"In the case of the rejection of the promise in question.ConclusionGenerally speaking, return await only makes a difference when return is involved by some block try/catch.If you need to treat the value that will be completed by a promise before to be actually returned, use return await. Otherwise, return (delegating the promise) makes no difference, since, as we have seen, every asynchronous function always returns a promise.Cold that there is no difference in runtime. The difference in fact is where the promise will be completed.Personally, I don't like to use return await because people do not actually understand this difference (often because they do not know that it exists). We convinced that JavaScript is and has always been a language with a huge number of subtle differences like this.The following code has the same effect as return await. The difference is that, in my view, it is clearer:function foo() {
try {
const val = await waitAndMaybeReject();
return val;
} catch (e) {
return 'caught';
}
}
It's the same as:function foo() {
try {
return await waitAndMaybeReject();
} catch (e) {
return 'caught';
}
}
It's up to you to decide which one you prefer.Like return await only has differential effect when inside blocks try/catch, the ESLint provides a rule called https://eslint.org/docs/rules/no-return-await that takes care of it for you.I don't believe you, show me all that!See the functional example below:fooWithReturn(true)
.then((resolvedValue) => console.log('1 fooWithReturn(throw).then =', resolvedValue)) // <não executará>
.catch((errorValue) => console.log('1 fooWithReturn(throw).catch =', errorValue)); // Erro não tratado!
fooWithReturn(false)
.then((resolvedValue) => console.log('2 fooWithReturn(dont throw).then =', resolvedValue)) // Yay!
.catch((errorValue) => console.log('2 fooWithReturn(dont throw).catch =', errorValue)); // <não executará>
fooWithReturnAwait(true)
.then((resolvedValue) => console.log('3 fooWithReturnAwait(throw).then =', resolvedValue)) // caught
.catch((errorValue) => console.log('3 fooWithReturnAwait(throw).catch =', errorValue)); // <não executará>
fooWithReturnAwait(false)
.then((resolvedValue) => console.log('4 fooWithReturnAwait(dont throw).then =', resolvedValue)) // Yay!
.catch((errorValue) => console.log('4 fooWithReturnAwait(dont throw).catch =', errorValue)); // <não executará>
async function fooWithReturn(shouldThrow) {
try {
return waitAndMaybeReject(shouldThrow);
} catch (e) {
return 'caught';
}
}
async function fooWithReturnAwait(shouldThrow) {
try {
return await waitAndMaybeReject(shouldThrow);
} catch (e) {
return 'caught';
}
}
function waitAndMaybeReject(shouldThrow) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (shouldThrow) {
reject('Erro não tratado!');
} else {
resolve('Yay!');
}
}, 500);
});
}Examples of this response were based on the article " https://jakearchibald.com/2017/await-vs-return-vs-return-await/ " by Jake Archibald.