Proper positioning of try/catch block in scenarios involving delayed async/await operations

For the past six months, I have been utilizing async/await and have truly enjoyed the convenience it provides. Typically, I adhere to the traditional usage like so:

try {
  await doSomethingAsync()
}
catch (e) {}

Lately, I've delved into experimenting with not immediately awaiting in order to execute additional code before waiting for the async data, such as:

let p = doSometiongAsync()
... perform more tasks
await p;

or:

let p1 = doJob1();
let p2 = doJob2();
... engage in more synchronous activities ...
await p1;
await p2;

The dilemma arises when considering where to properly place the try/catch blocks to ensure that errors, whether synchronous or asynchronous, within the calls are caught effectively. Should the try/catch block encompass the initial function call:

try {
   let p = doSomethingAsync() 
 } catch(errors) {}
 ... undertake actions ...
 await p

Should the try block be positioned around the await statement... or possibly two separate try blocks, one for each?

 try {
    let p = doSomethingAsync()
 } catch(errors) {}
 ... carry out tasks
 try {
     await p;
 } catch (evenmoreerrors) {}

Thank you!

Answer №1

Whether you need a try/catch block around the doSomethingAsync function depends on whether it is an async function or a non-async function that returns a promise.

If it's an async function...

...all you need is the try/catch around the await; an async function never throws synchronously, even if there's an exception in the synchronous part of it.

For example:

async function foo() {
  // This is part of the synchronous portion
  console.log("synchronous part of foo");
  if (true) {
    throw new Error();
  }
  return new Promise(resolve => {
    resolve();
  });
}

(async () => {
  const p = foo(); // No uncaught error
  try {
    await p;
  } catch (e) {
    console.log("Caught the error");
  }
})().catch(e => {
  console.log("Failed to catch it!");
});

If it's a non-async function that returns a promise...

...the need for try/catch blocks depends on how the function is written. If it could throw in its synchronous code, then you'll need a try/catch there. You also need one around the await in case the promise gets rejected.

For example, failing to handle the synchronous part:

function foo() {
  // This is part of the synchronous portion
  console.log("synchronous part of foo");
  if (true) {
    throw new Error();
  }
  return new Promise(resolve => {
    resolve();
  });
}

(async () => {
  const p = foo(); // No uncaught error
  try {
    await p;
  } catch (e) {
    console.log("Caught the error");
  }
})().catch(e => {
  console.log("Failed to catch it!");
});

And an example where promise rejection isn't caught:

function foo() {
  // This is part of the synchronous portion
  console.log("synchronous part of foo");
  return new Promise((resolve, reject) => {
    reject();
  });
}

(async () => {
  try {
    const p = foo();
  } catch (e) {
    console.log("Caught the error");
  }
  await p;
})().catch(e => {
  console.log("Failed to catch it!");
});

Answer №2

Errors can arise in both scenarios, one being in the asynchronous call result and another potentially occurring if there is logic prior to the return statement of the asynchronous call within a non-async function. The placement of the try/catch block should be determined by your specific logic requirements.

If you are certain that any potential errors will only occur during the asynchronous call itself, then it is advisable to include the try/catch block solely at the await statement.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Pass RGBA color code from JavaScript to Laravel controller

I have an exciting project where users need to select a color value in hex format. Once I retrieve this value in JavaScript, I convert it to Rgba format. Now, my challenge is figuring out how to send this converted value to the controller for database stor ...

Utilizing v-model for dynamic binding within a v-for iteration

I'm currently working on binding v-model dynamically to an object property within an array of objects. I am unsure about how to accomplish this task. The objective is to choose a user using the Select HTML tag and then display the list of that user&ap ...

Enhancing the Performance of jQuery Scripts

My jQuery function called textfill is utilized on numerous div elements. Essentially, it resizes the text inside each div to perfectly fit the container so that longer texts are made smaller than shorter ones while maintaining the maximum font size without ...

Using ES6 to generate objects within other objects

Dealing with data from a local API can be challenging, especially when you have limited control over the incoming data. However, I am looking to transform the data post my API call using a custom function. This is my current approach transformArray = () ...

Ways to retrieve the current URL in Next.js without relying on window.location.href or React Router

Is there a way to fetch the current URL in Next.js without relying on window.location.href or React Router? const parse = require("url-parse"); parse("hostname", {}); console.log(parse.href); ...

Sending JSON Data with Javascript Post Request

I've been attempting to send a JSON payload via a JavaScript script, but my webhooks don't seem to recognize the payload no matter what I try. Here is the code that I compiled from various online resources: let xhr = new XMLHttpRequest(); ...

Synchronous execution following a Node.js for loop integrated with callbacks

I'm facing a dilemma in my Nodejs application involving a for loop with callback functions. The loop iterates over an array, and for each value, an update operation is performed using a query, replacing the current value with the result of the query. ...

Default Selection Issue with Radio Buttons in AngularJS

I am currently encountering an issue with the code snippet included in my directive template '<li ng-repeat="f in foos">' + '<input type="radio" ng-change="foo(f.key)" ng-model="selectedFoo" name="foos" id="{{f.key}}" value="{{f.ke ...

Having trouble with Vue Router view not functioning properly in my Laravel Blade page

While diving into the world of Vue.js, I encountered a perplexing issue. After successfully running ExampleComponent.vue in my admin panel and displaying its content, I attempted to import routes from an external file (new_route_list.js) and load them via ...

Setting up an inline style @Input in Angular 2: A step-by-step guide

I am currently working on a component that needs to display random values, which will be generated randomly and passed through some @Input bindings in the template. Everything seems to be going well, but I am facing an issue when trying to link an @Input t ...

What is the best way to save an integer in HTML's localStorage instead of a string?

I've encountered an issue while using the localStorage feature in a game I'm developing. Specifically, the money variable should be increasing by 1 every second. Here's a snippet of my code: var money = 0; window.onload = function () { ...

Refrain from showing content beneath a certain element

Is there a way to hide all content that appears after a specific element, such as a particular class of div? The issue I am facing involves using a 1&1 webpage builder with a restrictive layout-template enforced by my boss. I am trying to remove the foote ...

The Gatsby + Typescript project is reporting that the module with the name "*.module.scss" does not have any exported members

I've recently gone through Gatsby's demo project in their documentation (which is long overdue for an update). I've carefully followed the instructions provided here: I've included an index.d.ts file in the /src directory of my project ...

Autocomplete Data Origin

I'm currently exploring the use of Typeahead and implementing AJAX to fetch my data source: $(document).ready(function() { $('input.typeahead').typeahead( { hint: true, highlight: true, m ...

Guide on incorporating pinching gestures for zooming in and out using JavaScript

I have been working on implementing pinch zoom in and out functionality in JavaScript. I have made progress by figuring out how to detect these gestures using touch events. var dist1=0; function start(ev) { if (ev.targetTouches.length == 2) {//checkin ...

Avoid Refreshing the Page When Pressing the Like Button

I've been working on code for liking a post and saving the value to a database using server-side code. However, I'm running into some issues when the page refreshes after clicking the like button. I tried using event.preventDefault() in my JavaSc ...

Error: Unspecified process.env property when using dotenv and node.js

I'm encountering an issue with the dotenv package. Here's the structure of my application folder: |_app_folder |_app.js |_password.env |_package.json Even though I have installed dotenv, the process.env variables are always u ...

Developing Java-based Ajax scripts

Is there a way to implement AJAX functionality in Java without actually using AJAX itself? I'm searching for a JAVA API that can achieve this. Just like we can submit data from a web page using a JAVA program, I want to handle AJAX operations through ...

React components featuring Material UI icons

I'm in need of assistance. I am looking for the Material UI icons, but I can't seem to find any information on how to obtain them. https://i.stack.imgur.com/FAUc7.jpg ...

Multiple asynchronous calls in Angular 2

In my Component, there is a function that is supposed to return a value (Promise). This value requires information from two distinct sources: an API call and data from a database. The method in question looks like this: public getValue(): Promise<numb ...