使用非立即异步/等待时,正确放置try / catch块

时间:2018-04-02 08:36:58

标签: javascript typescript async-await

我一直在使用async / await 6个月并且一直喜欢语法糖。我通常以传统的方式使用它:

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

最近我开始尝试不等待,以便在等待异步数据之前在此上下文中运行一些额外的代码,例如:

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

或:

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

问题是,try / catch块的正确位置在哪里,以确保正确捕获调用中的错误(同步或异步)。它是在初始函数调用周围:

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

或尝试阻止await ...或两个不同的try块,每个块一个?

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

THX!

2 个答案:

答案 0 :(得分:3)

这取决于doSomethingAsync是什么:async函数,或返回promise的非async函数。

如果它是async函数

...您只需try周围的catch / await; async函数永远不会同步抛出(即使它的初始同步部分抛出异常)。

示例:



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!");
});




如果它是一个非async函数,它返回一个promise

...然后根据功能的不同,您可能会在两个地方都需要try / catch,具体取决于它的编写方式。如果它可能会引入同步代码,那么你需要try / catch。如果拒绝承诺,您需要在try附近catch / await

不处理同步部分的示例:



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!");
});




未能捕获承诺拒绝的示例:



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!");
});




答案 1 :(得分:2)

在这两种情况下,如果在异步调用的return语句之前有一些逻辑,当你的函数不是{{}时,可能会发生错误,一个在异步调用结果中,另一个也可能发生。 1}}。这取决于您的逻辑位置async

如果您知道错误可能仅在异步调用时,请仅将try/catch放在try/catch语句中。