javascript 我可以在不使用 await 的情况下从 async 中捕获错误吗?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/30649994/
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-10-28 12:29:29  来源:igfitidea点击:

Can I catch an error from async without using await?

javascriptasync-awaitpromiseecmascript-7

提问by dvlsg

Can errors from a non-awaited async call be caught, sent to an original encapsulating try/catch, or raise an uncaught exception?

来自非等待异步调用的错误是否可以被捕获、发送到原始封装的 try/catch 或引发未捕获的异常?

Here's an example of what I mean:

这是我的意思的一个例子:

async function fn1() {
    console.log('executing fn1');
}

async function fn2() {
    console.log('executing fn2');
    throw new Error('from fn2');
}

async function test() {
    try {
        await fn1();
        fn2();
    }
    catch(e) {
        console.log('caught error inside test:', e);
    }
}

test();

In this scenario, the error thrown from fn2will be swallowed silently, and definitely not caught by the original try/catch. I believe this is expected behavior, since fn2is most likely being shoved off to the event loop to finish at some point in the future, and testdoesn't care when it finishes (which is intentional).

在这种情况下,抛出的错误fn2会被默默吞噬,绝对不会被原先捕捉到try/catch。我相信这是预期的行为,因为fn2很可能会被推到事件循环中以在将来的某个时候完成,并且test不关心它何时完成(这是有意的)。

Is there any way to ensure that errors are not accidentally swallowed by a structure like this, short of putting a try/catchinternal to fn2and doing something like emitting an error? I would even settle for an uncaught error without knowing how to catch it, I think -- I don't expect thrown errors to be typical program flow with what I am writing, but swallowing errors makes it relatively annoying to debug.

有没有办法确保错误不会被这样的结构意外吞下,而不是放置try/catch内部fn2并执行诸如发出错误之类的操作?我什至会在不知道如何捕获它的情况下接受一个未捕获的错误,我认为 - 我不希望抛出的错误是我正在编写的典型程序流程,但是吞下错误会使调试变得相对烦人。

Side note, I'm using Babel to transpile the code using the babel-runtime transform, and executing it with node.

旁注,我使用 Babel 使用 babel-runtime 转换来转译代码,并使用 node.js 执行它。

采纳答案by Michelle Tilley

Dealing with unhandled rejected native promises (and async/await uses native promises) is a feature supported now in V8. It's used in the latest Chrome to output debugging information when a rejected promise is unhandled; try the following at the Babel REPL:

处理未处理的被拒绝的原生承诺(并且 async/await 使用原生承诺)是 V8 现在支持的一个特性。它在最新的 Chrome 中用于在未处理被拒绝的承诺时输出调试信息;在Babel REPL 中尝试以下操作:

async function executor() {
  console.log("execute");
}

async function doStuff() {
  console.log("do stuff");
  throw new Error("omg");
}

function handleException() {
  console.error("Exception handled");
}

(async function() {
  try {
      await executor();
      doStuff();
  } catch(e) {
      handleException();
  }
})()

You see that, even though the exception from doStuff()is lost (because we're not using awaitwhen we call it), Chrome logs that a rejected promise was unhandled to the console:

您会看到,即使 from 的异常doStuff()丢失(因为我们在await调用它时没有使用),Chrome 仍会记录到控制台未处理被拒绝的承诺:

Screenshot

截屏

This is also available in Node.js 4.0+, though it requires listening to a special unhandledRejectionevent:

这在 Node.js 4.0+ 中也可用,但它需要监听一个特殊unhandledRejection事件

process.on('unhandledRejection', function(reason, p) {
    console.log("Unhandled Rejection at: Promise ", p, " reason: ", reason);
    // application specific logging, throwing an error, or other logic here
});

回答by Анатолий Ивашов

If you are familiar with promises, use them. If not, you can try this example to make you code more asynchronous :)

如果您熟悉promise,请使用它们。如果没有,你可以试试这个例子,让你的代码更加异步:)

function fn1(callback) {
    console.log('executing fn1');
    callback({status: true});
}

function fn2(callback) {
    console.log('executing fn2');
    callback({status: false});
}

function test() {
    fn1(function(result) {
        console.log('fn1 executed with status ' + result.status);
    });

    fn2(function(result) {
        console.log('fn2 executed with status ' + result.status);
        if (result.status == false) {
            console.log('error in fn2');
        }
    });
}

test();