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

What are some ways to provide the find() method in JavaScript with a specific search argument?

I've been exploring ways to search within an array while iterating through it. One method I stumbled upon is the find() method. Take a look at this example: var inventory = [ {name: 'apples', quantity: 2}, {name: 'bananas&apos ...

Is there a way to trigger Material-UI SpeedDialAction onClick events only when the SpeedDial is open and clicked, not when it is hovered over?

After making a modification to material-ui's <SpeedDial> component by removing the onMouseEnter={handleOpen} prop, I noticed that the onClick event within the <SpeedDialAction> component no longer triggers when clicking on a menu item. It ...

Display HTML content in autocomplete using jQuery UI

I implemented a search feature on my website using jQueryUI, similar to how it works on Facebook. Below is the jQuery code: //search main function split( val ) { return val.split( ); } function extractLast( term ) { return split( term ).pop(); } ...

Is Joi's existence a myth?

I've been using Joi for validation, and I've encountered a situation that I'm having trouble with. I have an object that sometimes includes an id field (for editing) and other times it doesn't (for creating). My goal is to validate tha ...

A guide on testing mouse clientY in React using JEST for effective testing

useEffect(() => { const mouseHandler = (event: MouseEvent) => { menuData.forEach((element) => { if (element.hasActiveDropdown && event.clientY > 50) { handleCloseDropDown(); // handleDropDown('0') ...

Managing components within an array

I have this array called match where match[0] = [2014-05-30 15:21:20,781] DEBUG [scheduler-4] (DiamondSchedulerRunner.java:41) Current node is not a manager of:publishEmail in tenant:0 [2014-05-30 15:21:20,781] DEBUG [scheduler-1] (DiamondSchedulerRunne ...

Disabling and enabling a link before and after an AJAX call using jQuery

I have been trying to disable a link before making an ajax call and then re-enable it right after receiving the response. However, my current approach doesn't seem to be working as expected: jQuery(this).prop('disabled', false); Here is my ...

Error Encountered with Nested Angular Material Tabs

Is there a way to prevent changes made to the upper tab in md-align-tabs attribute from affecting the inner tab when one tab is nested inside another using md-tabs? If so, how can I achieve this? <md-content layout="column" layout-fill> <md-ta ...

The Rtk query function does not generate endpoints

Having trouble with code splitting in RTK-query, it's not working for me and I can't figure out why App.jsx import React from "react"; import { Provider } from "react-redux"; import store, { persistor } from "store" ...

Modify the code to interpret a new JSON structure

I have a piece of code that is designed to read JSON data: $.getJSON("data.json", function(data){ var output = ''; $.each(data, function(index, value){ output += '<li>' + value.title + '</li>'; } ...

Comparing two inherited classes in Typescript: A step-by-step guide

Let's say we have two classes: Animal and Dog. The Dog class is a subclass of the Animal class. I am trying to determine the types of these objects. How can I accomplish this task? class Animal {} class Dog extends Animal {} //The object can be of ...

Angular 11 is throwing an error stating that the type 'Observable<Object>' is lacking certain properties as required by its type definition

My code is producing the following error: TS2739 (TS) Type 'Observable<Object>' is missing the following properties from type 'WeatherForecast': ID, date, temperatureC, temperatureF, summary I'm puzzled as to why this error ...

Expo's ReactNative camera feature fails to flip the camera view

Following the guidance provided in Expo Docs on how to use a camera, I have noticed that when I press the flip button, the state of the camera type changes from 0 to 1 and vice versa, but the camera always remains on the back side. This is my implementati ...

Quick method to populate an array with elements

I need to populate an array with a large number of objects. Currently, my approach looks like this: let useVertices = []; const len = this.indices.length; for(let i = 0; i < len; i++){ let index = this.indices[i]*3; useVertices.push(new THREE.Ve ...

Image loading failure detected in ReactJS

In my current project using Reactjs (Nextjs framework), I encountered an issue where I am unable to display an image on a page without specifying the "height" and "width" attributes in the Image tag. I attempted the following code snippet but the image is ...

Mastering the usage of Higher Order Components (HOC) with both types of props is

I am facing a challenge in implementing HOCs for this specific scenario. I aim to enclose existing components since they share similar functionalities. Below is an abridged version of my current structure: function CreateComponentHere(props: BaseProps): J ...

issue with deploying a software package and getting it installed

I developed a basic package containing only a simple <div> x </div> and published it using npm publish. When I attempted to install it in a project using npm i, I encountered the following error message: Support for the experimental syntax &apo ...

Issue with ng-checked not detecting boolean values retrieved from local storage

I'm working on a code snippet in my controller where I have a checkbox in my HTML with "ng-checked="enterToSend" and "ng-click="enterToSendCheck()" attached to it. $scope.enterToSend = localStorage.getItem('enterToSend'); $scope.enterToSen ...

Acquiring information from file within component operation

When a user drags and drops a file, how can I retrieve it from the drop event? HTML file <div (drop)="drop($event)" > drop file here </div> TS file drop (event) { console.log(event.target.files.length); // I need to retrieve the file her ...

Angular.js enables seamless synchronization between contenteditable elements and the $scope object by automatically updating the

I'm completely new to Angular.js and have been exploring various tutorials to grasp the concept of two-way binding with contenteditable elements within an ng-repeat. Currently, I am utilizing a shared 'store' between controllers like this: ...