Frontend Development 7 min read

Elegant Handling of async/await Exceptions in JavaScript

This article examines why try‑catch is often overused for async/await errors, outlines common scenarios that cause request failures, and presents two cleaner alternatives—using Promise .catch with conditional logic and the lightweight await‑to‑js utility—to simplify error handling and reduce code redundancy.

Rare Earth Juejin Tech Community
Rare Earth Juejin Tech Community
Rare Earth Juejin Tech Community
Elegant Handling of async/await Exceptions in JavaScript

Introduction

Many projects handle async/await exceptions with repetitive try‑catch blocks, which can clutter code and create redundancy. While try‑catch works, it often makes the logic harder to follow.

When Do Request Exceptions Occur?

Async requests may fail due to network disconnections or timeouts caused by slow connections.

When Should Exceptions Be Handled?

When an async request throws, JavaScript’s single‑threaded nature stops subsequent code execution, so handling the error allows the program to continue.

Serial Async Requests

try {
  // Get list
  const list = await getList(params);
  // Get details using first item
  const info = await getListById(list[0]?.id);
} catch {}

If the first request fails, subsequent requests will also fail, necessitating error handling.

Managing Loading State

loading.value = true;
try {
  const list = await getList(params);
} finally {
  loading.value = false;
}

Without a try‑catch, a failed request could leave the UI stuck in a loading state, so the finally block ensures the loading flag is reset.

Cleaner Handling Methods

Using Promise .catch

Since await returns a Promise, you can attach .catch to handle errors and use an if statement to exit early, avoiding unnecessary try‑catch blocks.

loading.value = true;
let res = await getList().catch(() => (loading.value = false));
if (!res) return;
// Continue with successful response

await‑to‑js Utility

The await-to-js library provides a to function that returns a tuple [err, data] , eliminating the need for try‑catch.

/**
 * @param { Promise } promise
 * @param { Object= } errorExt - Additional info for the error object
 * @return { Promise }
 */
export function to
(
  promise: Promise
,
  errorExt?: object
): Promise<[U, undefined] | [null, T]> {
  return promise
    .then<[null, T]>((data: T) => [null, data])
    .catch<[U, undefined]>((err: U) => {
      if (errorExt) {
        const parsedError = Object.assign({}, err, errorExt);
        return [parsedError, undefined];
      }
      return [err, undefined];
    });
}
export default to;

Usage example:

import to from 'await-to-js';

const [err, data] = await to(getList(params));
if (err) return;
// Process data

Conclusion

The article demonstrates two concise approaches—Promise .catch with conditional checks and the await-to-js helper—to replace repetitive try‑catch blocks, resulting in cleaner, more maintainable async/await code.

JavaScripterror handlingasyncawaittry-catchawait-to-js
Rare Earth Juejin Tech Community
Written by

Rare Earth Juejin Tech Community

Juejin, a tech community that helps developers grow.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.