‘return await promise’ vs ‘return promise’ in JavaScript

“Return await promise” and “return promise” in JavaScript

When returning a result from a promise from an asynchronous function, you can either wait for the promise to complete before returning an await promise, or you can return a return promise directly:

async function func1() {
  const promise = asyncOperation();
  return await promise;
}

// vs
async function func2() {
  const promise = asyncOperation();
  return promise;
}
Copy the code

You will soon see that both of these expressions execute effectively.

But are there situations where these expressions behave differently? Let’s find out!

1, The Same behavior

To find the difference between these two expressions (return await promise and return promise), a helper function promisedDivision(n1, n2) is used. This function divides two arguments and returns the result wrapped in a Promise:

function promisedDivision(n1, n2) {
  if (n2 === 0) {
    return Promise.reject(new Error('Cannot divide by 0'));
  } else {
    return Promise.resolve(n1 / n2); }}Copy the code

If the second (divisor) argument is 0, the function returns a Promise reject, because dividing by 0 is impossible.

Ok, so with the helper function defined, let’s divide some numbers.

The following function divideWithAwait() returns the result of 6 divided by 2 wrapped in a promise using the return await promiseDivision(6, 2) expression:

async function divideWithAwait() {
  return await promisedDivision(6.2);
}

async function run() {
  const result = await divideWithAwait();
  console.log(result); // logs 3
}
run();
Copy the code

Inside the run() function, wait for divideWithAwait() to return the result, and inside the divideWithAwait() function wait for the promisedDivision(6, 2) to return the result. Everything is normal.

Now let’s try using the second expression without the await keyword and return promiseDivision(6, 2) with the result of division wrapped directly:

async function divideWithoutAwait() {
  return promisedDivision(6.2);
}

async function run() {
  const result = await divideWithoutAwait();
  console.log(result); // logs 3
}
run();
Copy the code

Even if the await keyword is not used in divideWithoutAwait(), the expression divideWithoutAwait() in the run() function still correctly evaluates the 6/2 division to 3!

In this step, you have seen that there is no difference between using return await promise and return Promise. At least when dealing with the Promise of success.

But let’s explore further!

2, Different behavior

Now let’s take a different approach, especially when trying to deal with implementing promise.reject. To make the function promiseDivision(n1, n2) return a reject promise, we set the second parameter to 0.

Because promiseDivision(n1, 0) now returns reject, let’s put the execution in a try {… } catch (error) {… } — to see if a reject promise was caught.

Ok, let’s use a return await promiseDivision(5, 0) expression with await keyword:

async function divideWithAwait() {
  try {
    return await promisedDivision(5.0);
  } catch (error) {
    // Rejection caught
    console.log(error); // logs Error('Cannot divide by 0')}}async function run() {
  const result = await divideWithAwait();
  console.log(result); // logs undifined
}
run();
Copy the code

Because dividing by zero is impossible, promiseDivision(5, 0) returns a Reject promise. catch(error) { … } successfully captured a Reject promise thrown by promiseDivision(5, 0).

What’s the second way to omit await?

async function divideWithoutAwait() {
  try {
    return promisedDivision(5.0);
  } catch (error) {
    // Rejection NOT caught
    console.log(error); }}async function run() {
  const result = await divideWithoutAwait();
}
run(); // Uncaught Error: Cannot divide by 0
Copy the code

However, this time catch(error) {… } No promise to catch reject.

Now you can easily see the main difference between using return await promise and return promise:

When being wrapped into try { ... }, the nearby catch(error) { ... } catches the rejected promise only if the promise is awaited (which is true for return await promise).

When put into try {… } catch (error) {… }, only if the promise is await (return await promise), the latest catch(error) {… } will capture the promise reject result!

3. Conclusion

In most cases, especially if a Promise returns a resolve, there is little difference between return await promises and return promises.

However, if you want to capture the reject result of a promise from the 1 return result of an asynchronous function, you should explicitly use return await promise expressions and intentionally await them!

try {… catch(error) {… } statements can only catch reject promises waiting to be executed!