Skip to main content

JavaScript Asynchronous

JavaScript async Error Handling

Written by Published

try and catch handle errors in async functions the same way as anywhere else.

A rejected promise that is awaited throws.

That means ordinary try and catch work on asynchronous code.

Example

Example

javascript

async function run() {
  try {
    await Promise.reject(new Error("no network"));
  } catch (error) {
    console.log("caught: " + error.message);
  }
}

run();

The output is caught: no network.

Errors in async Functions

Awaiting a rejected promise throws the rejection reason.

try and catch around the await handle it.

An uncaught error inside an async function rejects the promise it returns.

Syntax

Syntax

javascript

try {
  const value = await promise;
} catch (error) {
  // handle it
}

This is the same try and catch as anywhere else.

Wrapping Several Awaits

One try can cover a whole sequence of steps.

Example

Example

javascript

function step(n) {
  return n === 2 ? Promise.reject(new Error("step two failed")) : Promise.resolve(n);
}

async function run() {
  try {
    await step(1);
    await step(2);
    console.log("never reached");
  } catch (error) {
    console.log(error.message);
  }
}

run();

The first failure jumps straight to the catch.

finally for Cleanup

It runs whether the work succeeded or failed.

Example

Example

javascript

async function run() {
  try {
    await Promise.reject(new Error("failed"));
  } catch (error) {
    console.log("handled");
  } finally {
    console.log("tidied up");
  }
}

run();

The output is handled then tidied up.

An Uncaught Error Rejects

An async function that throws returns a rejected promise.

The caller can catch it in the usual way.

Example

Example

javascript

async function run() {
  throw new Error("inside");
}

run().catch(function (error) {
  console.log("caught outside: " + error.message);
});

The error escaped the function as a rejection.

Catching at the Call Site

Whether you handle it inside or outside is a design choice.

Example

Example

javascript

async function load() {
  return await Promise.reject(new Error("gone"));
}

async function main() {
  try {
    await load();
  } catch (error) {
    console.log("main handled it: " + error.message);
  }
}

main();

Letting it bubble up keeps the lower function simpler.

Do Not Forget to Catch

Calling an async function without handling its rejection gives an unhandled rejection.

This is easy to miss because nothing looks wrong at the call site.

Example

Example

javascript

async function risky() {
  throw new Error("boom");
}

risky().catch(function (error) {
  console.log("handled: " + error.message);
});

Writing just risky(); would leave the rejection unhandled.

Complete Example

Complete Example

html

<!DOCTYPE html>
<html>
<head>
  <title>JavaScript async Error Handling</title>
</head>
<body>

  <h1>async Error Handling</h1>

  <p id="out">Loading...</p>

  <script>
    function loadUser(id) {
      return new Promise(function (resolve, reject) {
        setTimeout(function () {
          if (id > 0) {
            resolve("Ada");
          } else {
            reject(new Error("invalid id"));
          }
        }, 500);
      });
    }

    async function show() {
      const out = document.getElementById("out");
      try {
        const name = await loadUser(0);
        out.textContent = "Welcome, " + name;
      } catch (error) {
        out.textContent = "Failed: " + error.message;
      } finally {
        console.log("finished");
      }
    }

    show();
  </script>

</body>
</html>

Try It Yourself

Run the above example in the Try It Editor.

Try a valid id:

Change loadUser(0) to loadUser(1) and see the success path.

Important Points

  • Awaiting a rejected promise throws.
  • try and catch handle it normally.
  • One try can cover several awaits.
  • finally runs either way.
  • An uncaught error rejects the promise the async function returns.

Conclusion

Error handling in async code uses the same tools as everywhere else.

That is a large part of why async and await are easier to read.

The rule stays the same: every asynchronous call needs somewhere for failure to go.