如何在promise中的回调中捕获Uncaught异常

时间:2017-08-18 16:24:11

标签: node.js callback promise uncaught-exception

我对node.js有一个很大的问题。

有关信息,我使用版本0.12,因为我们的应用程序非常复杂和庞大,无法将easilly迁移到最新版本。

而且,有了这个,许多函数都是回调函数。

但是,在这个项目的新部分中,我想使用Promises来轻松捕获错误。我遇到了事件循环中未捕获异常的问题。

这是测试代码:

process.on('uncaughtException', function (err) {
    console.error('Uncaught Exception');
});

new Promise(function () {
    process.nextTick(function () {
        var a = null;

        a.b;
    });
}).catch(function (e) {
    console.log('catched by Promise');
});

如果我测试此代码,系统地将其传递到uncaughtException

可以用promises捕获这种类型的错误吗?

由于

1 个答案:

答案 0 :(得分:2)

Promises将在两个地方自动捕获异常:1)在Promise执行器函数中,2)在.then().catch()处理程序中。在这两种情况下,他们都会抓住异常并将其变成被拒绝的承诺。以下是几个例子:

// Promise executor
new Promise(function(resolve, reject) {
    var a = null;
    a.b = 0;      // throws an exception
    resolve("done");
}).then(function(data) {
    console.log(data);     // never gets here
}).catch(function(err) {
    console.log(err);      // shows the above exception
});

// .then() handler
Promise.resolve().then(function(data) {
    var a = null;
    a.b = 0;      // throws an exception
    return "hello";
}).then(function(data) {
    console.log(data);     // never gets here
}).catch(function(err) {
    console.log(err);      // shows the above exception
});

因此,如果您宣传所有异步操作,以便所有完成或错误处理程序都是.then()处理程序或.catch()处理程序,那么promise基础结构将捕获所有这些异常。但是,它不会在这些情况之外捕获异常。如果你正在使用setTimeout()或任何其他未包含在promise中的异步操作,那么你必须自己将这些回调包装在try / catch中。但是,这很简单。而不是setTimeout()可以使用基于承诺的简单函数:

所以,而不是:

setTimeout(someFunction, 100);

您可以使用:

delay(10).then(someFunction).catch(...);

delay()的实施是这样的:

function delay(t) {
    return new Promise(function(resolve) {
        setTimeout(resolve, t);
    });
}

现在,someFunction()中的所有同步异常都会被捕获。如果它执行自己的异步操作,那么那些也必须转换为使用promises。

当然,您可以将自己的try / catch包装在其他情况下,以便在其他地方捕获您自己的异常。

您可以使用Bluebird的Promise.promisifyAll()之类的东西来制作整个界面的默认版本。例如,我一直使用fs模块来创建整个fs接口的promisified版本,因此我可以使用promises来处理所有文件访问。您可以在此处详细了解使用Bluebird的原因:Are there still reasons to use promise libraries like Q or BlueBird now that we have ES6 promises?

在您的具体示例中:

new Promise(function () {
    process.nextTick(function () {
        var a = null;

        a.b;
    });
}).catch(function (e) {
    console.log('catched by Promise');
});

您在异步回调中抛出异常,这不是承诺为您捕获异常的条件之一。我能想到的主要是:

// wrapper function to run a function upon nextTick and catch exceptions in it
function nextTick(fn) {
    return new Promise(function(resolve, reject) {
        process.nextTick(function() {
            try {
                resolve(fn());
            } catch(e) {
                reject(e);
            }
        });
    });
}

nextTick(function() {
     var a = null;
     a.b = 0;            // throw exception
}).catch(function(e) {
     // catches exception here
});

当然,您也可以自己捕获异常并在本地处理它,但是如果没有承诺就很难将错误传播回更高级别:

 process.nextTick(function () {
     try {
         var a = null;
         a.b = 0;
     } catch(e) {
          // handle exception here
     }
 });