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

时间:2015-06-04 17:05:40

标签: javascript async-await promise ecmascript-7

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

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

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();

在这种情况下,fn2引发的错误将被静默吞噬,并且绝对不会被原始try/catch捕获。我认为这是预期的行为,因为fn2最有可能被推到事件循环中,以便在将来的某个时刻完成,而test在完成时并不关心(这是故意)。

有没有办法确保错误不会被这样的结构意外吞没,而不是将try/catch内部放到fn2并做一些像发出错误的事情?我甚至会在不知道如何捕获它的情况下解决一个未被捕获的错误,我认为 - 我不希望抛出的错误成为我正在编写的典型程序流程,但是吞下错误会使调试相对烦人。 / p>

旁注,我使用Babel使用babel-runtime变换来转换代码,并使用节点执行它。

2 个答案:

答案 0 :(得分:27)

处理未处理的被拒绝的本机承诺(以及async / await使用本机承诺)是V8中现在支持的功能。当被拒绝的承诺未处理时,它在最新的Chrome中用于输出调试信息;请在the 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();
  }
})()

您可以看到,即使doStuff()中的例外信息丢失(因为我们在调用它时我们没有使用await),Chrome会记录拒绝的承诺未处理到控制台:

Screenshot

这也可以在Node.js 4.0+中使用,但它需要收听a special unhandledRejection event

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

答案 1 :(得分:-7)

如果您熟悉promises,请使用它们。如果没有,您可以尝试此示例以使您的代码更加异步:)

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();