在 JavaScript 中的异步函数中捕获所有 Promise 拒绝

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/46712602/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 03:34:18  来源:igfitidea点击:

Catching All Promise Rejections in an Async Function in JavaScript

javascripterror-handlingasync-awaites6-promise

提问by MFave

I've ran into an issue with catching all the errors when multiple promises throw rejection errors after being awaited in an async function (javaScript - node v8.4.0).

当多个承诺在异步函数(javaScript - node v8.4.0)中等待后抛出拒绝错误时,我遇到了捕获所有错误的问题。

Make reference to the following javaScript:

参考以下javaScript:

For reference, the functions timeoutOne() and timeoutTwo() simply return a native promise that resolves a value after a 1 and 2 second timeout respectively, or reject with an error if I set "deviousState" to true.

作为参考,函数 timeoutOne() 和 timeoutTwo() 简单地返回一个本机承诺,该承诺分别在 1 秒和 2 秒超时后解析一个值,或者如果我将“deviousState”设置为 true,则拒绝并显示错误。

let deviousState = true;

async function asyncParallel() {
  try {
    let res1 = timeoutOne();
    let res2 = timeoutTwo();
    console.log(`All done with ${await res1} ${await res2}`)
  }
  catch(err) {
    console.log(err)
  }
}
asyncParallel();

let pAll = Promise.all([timeoutOne(), timeoutTwo()]);
pAll.then((val) => {
  console.log(`All done with ${val[0]} ${val[1]}`)
}).catch(console.log);

In both cases only the promise that returns first logs an error. I know that in some promise libraries there is a way to log all the errors (for example the "settle" method in bluebird), however, I'm not sure if there is an analogue to this method in native promises?

在这两种情况下,只有首先返回的承诺才会记录错误。我知道在某些 Promise 库中,有一种方法可以记录所有错误(例如 bluebird 中的“settle”方法),但是,我不确定本机 Promise 中是否有与此方法类似的方法?

Also, if both promises reject, then asyncParallel() logs an uncaught error with the promise that rejects last. Is that because there is no built in mechanism for async function's try / catch blocks to catch multiple rejections in this way?

此外,如果两个 Promise 都拒绝,则 asyncParallel() 会记录一个未捕获的错误,并带有最后拒绝的 Promise。那是因为异步函数的 try / catch 块没有内置机制来以这种方式捕获多个拒绝吗?

Everything works the same in both instances if the promises resolve. Its just that when both reject, the Promise.all handles the errors, and the async function version states that one of the unhandled promise errors will crash the process in future versions of node.

如果承诺解决,则在这两种情况下一切都相同。只是当两者都拒绝时,Promise.all 会处理错误,而 async 函数版本声明未处理的承诺错误之一将在未来版本的节点中导致进程崩溃。

Is there anyway for try / catch to handle this type of error correctly? Or do I still need to use a Promise.all inside async functions to make sure that the errors are handled correctly?

无论如何,try / catch 是否可以正确处理此类错误?还是我仍然需要在异步函数中使用 Promise.all 来确保正确处理错误?

回答by Bergi

If both promises reject, then asyncParallel()logs an uncaught error with the promise that rejects last.

如果两个 Promise 都拒绝,那么asyncParallel()最后拒绝的 Promise 会记录一个未捕获的错误。

Yes - you created the timeoutTwo()promise but never handled its errors (like using it in an await). The await res2was never executed due to the exception in await res1.

是的 - 您创建了timeoutTwo()Promise,但从未处理过它的错误(比如在 中使用它await)。在await res2从未因异常执行await res1

(Notice it's not "the promise that rejects last", but always the promise that is awaited second).

(请注意,这不是“最后拒绝的承诺”,而是第二个等待的承诺)。

Is that because there is no built in mechanism for async function's try / catch blocks to catch multiple rejections in this way?

那是因为异步函数的 try / catch 块没有内置机制来以这种方式捕获多个拒绝吗?

In sequential code, there cannot be multiple exceptions, so coming up with extra syntax to deal with them would be hard.

在顺序代码中,不可能有多个异常,所以想出额外的语法来处理它们会很困难。

Do I still need to use a Promise.allinside async functions to make sure that the errors are handled correctly?

我是否仍然需要使用Promise.all内部异步函数来确保正确处理错误?

Yes, exactly that. If you want to wait for multiple promises in parallel, you should alwaysuse Promise.all. The awaitkeyword is just sugar for the following .then()call.

是的,正是如此。如果要并行等待多个 Promise,则应始终使用Promise.all. 该await关键字是以下只是糖.then()的呼叫。

You should write

你应该写

async function asyncParallel() {
  try {
    let [val1, val2] = await Promise.all([timeoutOne(), timeoutTwo()]);
    console.log(`All done with ${val1} ${val2}`)
  } catch(err) {
    console.log(err)
  }
}

In both cases only the promise that returns first logs an error. I know that in some promise libraries there is a way to log all the errors (for example the "settle" method in bluebird), however, I'm not sure if there is an analogue to this method in native promises?

在这两种情况下,只有首先返回的承诺才会记录错误。我知道在某些 Promise 库中,有一种方法可以记录所有错误(例如 bluebird 中的“settle”方法),但是,我不确定本机 Promise 中是否有与此方法类似的方法?

No, there's not. The characteristics of settleare trivial to implement yourself using then, with any values you desire:

不,没有。settle使用 实现自己的特征是微不足道的then,具有您想要的任何值:

async function asyncParallel() {
  try {
    let [stat1, stat2] = await Promise.all([
        timeoutOne().then(() => "one fulfilled", () => "one rejected"), 
        timeoutTwo().then(() => "two fulfilled", () => "two rejected")
    ]);
    console.log(`All settled with ${stat1} ${stat2}`)
  } catch(err) {
    console.log(err)
  }
}