await vs return vs return await

When writing async functions, there are differences between await vs return vs return await, and picking the right one is important.

Let’s start with this async function:

async function waitAndMaybeReject() {
  // Wait one second
  await new Promise(r => setTimeout(r, 1000));
  // Toss a coin
  const isHeads = Boolean(Math.round(Math.random()));

  if (isHeads) return 'yay';
  throw Error('Boo!');
}

This returns a promise that waits a second, then has a 50/50 chance of fulfilling with "yay" or rejecting with an error. Let’s use it in a few subtlety different ways:

Just calling

async function foo() {
  try {
    waitAndMaybeReject();
  }
  catch (e) {
    return 'caught';
  }
}

Here, if you call foo, the returned promise will always fulfill with undefined, without waiting.

Since we don’t await or return the result of waitAndMaybeReject(), we don’t react to it in any way. Code like this is usually a mistake.

Awaiting

async function foo() {
  try {
    await waitAndMaybeReject();
  }
  catch (e) {
    return 'caught';
  }
}

Here, if you call foo, the returned promise will always wait one second, then either fulfill with undefined, or fulfill with "caught".

Because we await the result of waitAndMaybeReject(), its rejection will be turned into a throw, and our catch block will execute. However, if waitAndMaybeReject() fulfills, we don’t do anything with the value.

Returning

async function foo() {
  try {
    return waitAndMaybeReject();
  }
  catch (e) {
    return 'caught';
  }
}

Here, if you call foo, the returned promise will always wait one second, then either fulfill with "yay", or reject with Error('Boo!').

By returning waitAndMaybeReject(), we’re deferring to its result, so our catch block never runs.

Return-awaiting

The thing you want in try/catch blocks, is return await:

async function foo() {
  try {
    return await waitAndMaybeReject();
  }
  catch (e) {
    return 'caught';
  }
}

Here, if you call foo, the returned promise will always wait one second, then either fulfill with "yay", or fulfill with "caught".

Because we await the result of waitAndMaybeReject(), its rejection will be turned into a throw, and our catch block will execute. If waitAndMaybeReject() fulfills, we return its result.

If the above seems confusing, it might be easier to think of it as two separate steps:

async function foo() {
  try {
    // Wait for the result of waitAndMaybeReject() to settle,
    // and assign the fulfilled value to fulfilledValue:
    const fulfilledValue = await waitAndMaybeReject();
    // If the result of waitAndMaybeReject() rejects, our code
    // throws, and we jump to the catch block.
    // Otherwise, this block continues to run:
    return fulfilledValue;
  }
  catch (e) {
    return 'caught';
  }
}

Note: Outside of try/catch blocks, return await is redundant. There’s even an ESLint rule to detect it, but it allows it in try/catch.


This content originally appeared on Jake Archibald's blog and was authored by Jake Archibald's blog

When writing async functions, there are differences between await vs return vs return await, and picking the right one is important.

Let's start with this async function:

async function waitAndMaybeReject() {
  // Wait one second
  await new Promise(r => setTimeout(r, 1000));
  // Toss a coin
  const isHeads = Boolean(Math.round(Math.random()));

  if (isHeads) return 'yay';
  throw Error('Boo!');
}

This returns a promise that waits a second, then has a 50/50 chance of fulfilling with "yay" or rejecting with an error. Let's use it in a few subtlety different ways:

Just calling

async function foo() {
  try {
    waitAndMaybeReject();
  }
  catch (e) {
    return 'caught';
  }
}

Here, if you call foo, the returned promise will always fulfill with undefined, without waiting.

Since we don't await or return the result of waitAndMaybeReject(), we don't react to it in any way. Code like this is usually a mistake.

Awaiting

async function foo() {
  try {
    await waitAndMaybeReject();
  }
  catch (e) {
    return 'caught';
  }
}

Here, if you call foo, the returned promise will always wait one second, then either fulfill with undefined, or fulfill with "caught".

Because we await the result of waitAndMaybeReject(), its rejection will be turned into a throw, and our catch block will execute. However, if waitAndMaybeReject() fulfills, we don't do anything with the value.

Returning

async function foo() {
  try {
    return waitAndMaybeReject();
  }
  catch (e) {
    return 'caught';
  }
}

Here, if you call foo, the returned promise will always wait one second, then either fulfill with "yay", or reject with Error('Boo!').

By returning waitAndMaybeReject(), we're deferring to its result, so our catch block never runs.

Return-awaiting

The thing you want in try/catch blocks, is return await:

async function foo() {
  try {
    return await waitAndMaybeReject();
  }
  catch (e) {
    return 'caught';
  }
}

Here, if you call foo, the returned promise will always wait one second, then either fulfill with "yay", or fulfill with "caught".

Because we await the result of waitAndMaybeReject(), its rejection will be turned into a throw, and our catch block will execute. If waitAndMaybeReject() fulfills, we return its result.

If the above seems confusing, it might be easier to think of it as two separate steps:

async function foo() {
  try {
    // Wait for the result of waitAndMaybeReject() to settle,
    // and assign the fulfilled value to fulfilledValue:
    const fulfilledValue = await waitAndMaybeReject();
    // If the result of waitAndMaybeReject() rejects, our code
    // throws, and we jump to the catch block.
    // Otherwise, this block continues to run:
    return fulfilledValue;
  }
  catch (e) {
    return 'caught';
  }
}

Note: Outside of try/catch blocks, return await is redundant. There's even an ESLint rule to detect it, but it allows it in try/catch.


This content originally appeared on Jake Archibald's blog and was authored by Jake Archibald's blog


Print Share Comment Cite Upload Translate Updates
APA

Jake Archibald's blog | Sciencx (2017-12-07T13:23:56+00:00) await vs return vs return await. Retrieved from https://www.scien.cx/2017/12/07/await-vs-return-vs-return-await/

MLA
" » await vs return vs return await." Jake Archibald's blog | Sciencx - Thursday December 7, 2017, https://www.scien.cx/2017/12/07/await-vs-return-vs-return-await/
HARVARD
Jake Archibald's blog | Sciencx Thursday December 7, 2017 » await vs return vs return await., viewed ,<https://www.scien.cx/2017/12/07/await-vs-return-vs-return-await/>
VANCOUVER
Jake Archibald's blog | Sciencx - » await vs return vs return await. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2017/12/07/await-vs-return-vs-return-await/
CHICAGO
" » await vs return vs return await." Jake Archibald's blog | Sciencx - Accessed . https://www.scien.cx/2017/12/07/await-vs-return-vs-return-await/
IEEE
" » await vs return vs return await." Jake Archibald's blog | Sciencx [Online]. Available: https://www.scien.cx/2017/12/07/await-vs-return-vs-return-await/. [Accessed: ]
rf:citation
» await vs return vs return await | Jake Archibald's blog | Sciencx | https://www.scien.cx/2017/12/07/await-vs-return-vs-return-await/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.