Ad

Correct Placement Of Try/catch Block When Using Non-immediate Async/await

- 1 answer

I've been using async/await for 6 months and been loving the syntactic sugar. I typically use it the traditional way:

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

Recently I've started experimenting with not awaiting immediately so that i run some extra code in this context before waiting for the async data, like:

let p = doSometiongAsync()
... do more stuff
await p;

or:

let p1 = doJob1();
let p2 = doJob2();
... do more synchronous stuff ...
await p1;
await p2;

The question is, where is the correct placement of the try/catch blocks to make sure errors (either synchronous or asynchronous) within the calls are caught properly. Is it around the initial function call:

try {
   let p = doSomethingAsync() 
 } catch(errors) {}
 ... do stuff ...
 await p

or try block around the await... or two different try blocks, one for each?

 try {
    let p = doSomethingAsync()
 } catch(errors) {}
 ... do stuff
 try {
     await p;
 } catch (evenmoreerrors) {}

thx!

Ad

Answer

It depends on what doSomethingAsync is: An async function, or a non-async function that returns a promise.

If it's an async function

...you just need the try/catch around the await; an async function never throws synchronously (even if the exception is thrown by the initial synchronous portion of it).

Example:

async function foo() {
  // Note this is in 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

...then depending on the function, you may need try/catch in both places, or not, depending on how it's written. If it may throw in its synchronous code, you need try/catch around that. And you need try/catch around the await in case of promise rejection.

Example of not handling the synchronous part:

function foo() {
  // Note this is in 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!");
});

Example of failing to catch the promise rejection:

function foo() {
  // Note this is in 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!");
});

Ad
source: stackoverflow.com
Ad