如何在承诺的回调中捕获未捕获的异常
How to catch an Uncaught exception in a callback in a promise
我对 node.js 有很大的疑问。
作为参考,我使用了 0.12 版本,因为我们的应用程序非常复杂和庞大,无法轻松迁移到最新版本。
因此,许多函数都是回调函数。
但是,在这个项目的新部分,我想使用 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 捕获此类错误?
谢谢
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()
处理程序,那么承诺基础结构将捕获所有这些中的异常。但是,它不会捕获这些情况之外的异常。如果您正在使用 setTimeout()
或任何其他未包装在承诺中的异步操作,那么您将必须自己将这些回调包装在 try/catch 中。但是,做起来很简单。可以使用基于 promise 的简单函数代替 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
接口的承诺版本,因此我可以对所有文件访问功能使用承诺。您可以在此处查看更多关于使用 Bluebird 的原因:
在您的具体示例中:
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
}
});
我对 node.js 有很大的疑问。
作为参考,我使用了 0.12 版本,因为我们的应用程序非常复杂和庞大,无法轻松迁移到最新版本。
因此,许多函数都是回调函数。
但是,在这个项目的新部分,我想使用 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 捕获此类错误?
谢谢
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()
处理程序,那么承诺基础结构将捕获所有这些中的异常。但是,它不会捕获这些情况之外的异常。如果您正在使用 setTimeout()
或任何其他未包装在承诺中的异步操作,那么您将必须自己将这些回调包装在 try/catch 中。但是,做起来很简单。可以使用基于 promise 的简单函数代替 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
接口的承诺版本,因此我可以对所有文件访问功能使用承诺。您可以在此处查看更多关于使用 Bluebird 的原因:
在您的具体示例中:
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
}
});