为什么 Promise 不捕获异步操作抛出的错误?
Why doesn't Promise catch error thrown by async operation?
给定以下代码:
var fs = require('fs');
var asyncErrorPromise = new Promise(function(resolve) {
fs.readFile('does/not/exist.blah', function(fileError, content) {
if (fileError) throw fileError;
resolve(content);
});
});
asyncErrorPromise
.then(function(content) {
console.log('content received: ' + content);
})
.catch(function(err) {
console.log('error received: ' + err.name);
});
我希望抛出的 fileError
(因为我尝试加载的文件不存在)将被 Promise 捕获并汇集到 .catch()
语句中。所以最后我会得到这个输出:error received: ENOENT
.
但是,当我 运行 这段代码时,我得到以下代码:
if (err) throw err;
^
Error: ENOENT: no such file or directory, open 'does/not/exist.blah'
at Error (native)
所以错误没有被捕获:它像往常一样抛出,就好像它在 Promise 之外。
为什么会这样?
我能找到的关于 Promises 的所有内容都更关心错误被悄悄吞噬,而不是这个问题,它实际上在你不希望它抛出的地方抛出!
我应该如何实现我的意图?我需要使用 try-catch 语句和 reject
处理程序吗?
您无法捕获使用 promise 的异步回调函数中抛出的错误,因为它的上下文将会丢失。在您使用 Node 的情况下,您将在 process.on('uncaughtException')
处理程序中丢失错误的上下文,并且回调将 运行 作为事件队列中自己的事件,具有自己的上下文和范围。
使用承诺,正确的解决方案是 reject
包装承诺。
另一种方法是使用 Domain
对象 (Domain documentation),但它正在等待弃用。使用 domain
您可以维护上下文并为您的错误注册一个处理程序,如下所示。
var domain = require('domain');
var d = domain.create();
d.on('error', function(err){
//Do something with your error
});
d.run(function(){
//Run your async code that might throw error
});
给定以下代码:
var fs = require('fs');
var asyncErrorPromise = new Promise(function(resolve) {
fs.readFile('does/not/exist.blah', function(fileError, content) {
if (fileError) throw fileError;
resolve(content);
});
});
asyncErrorPromise
.then(function(content) {
console.log('content received: ' + content);
})
.catch(function(err) {
console.log('error received: ' + err.name);
});
我希望抛出的 fileError
(因为我尝试加载的文件不存在)将被 Promise 捕获并汇集到 .catch()
语句中。所以最后我会得到这个输出:error received: ENOENT
.
但是,当我 运行 这段代码时,我得到以下代码:
if (err) throw err;
^
Error: ENOENT: no such file or directory, open 'does/not/exist.blah'
at Error (native)
所以错误没有被捕获:它像往常一样抛出,就好像它在 Promise 之外。
为什么会这样?
我能找到的关于 Promises 的所有内容都更关心错误被悄悄吞噬,而不是这个问题,它实际上在你不希望它抛出的地方抛出!
我应该如何实现我的意图?我需要使用 try-catch 语句和 reject
处理程序吗?
您无法捕获使用 promise 的异步回调函数中抛出的错误,因为它的上下文将会丢失。在您使用 Node 的情况下,您将在 process.on('uncaughtException')
处理程序中丢失错误的上下文,并且回调将 运行 作为事件队列中自己的事件,具有自己的上下文和范围。
使用承诺,正确的解决方案是 reject
包装承诺。
另一种方法是使用 Domain
对象 (Domain documentation),但它正在等待弃用。使用 domain
您可以维护上下文并为您的错误注册一个处理程序,如下所示。
var domain = require('domain');
var d = domain.create();
d.on('error', function(err){
//Do something with your error
});
d.run(function(){
//Run your async code that might throw error
});