【发布时间】:2015-10-09 20:38:14
【问题描述】:
我使用“promise”(但也尝试过“bluebird”)npm 模块大量使用 Promises 来包装异步代码。而且我对它不处理异步抛出并不感到惊讶:
var Promise = require("promise"); // also tried require("bluebird") here
function asyncThrow()
{
return new Promise(function(resolve, reject) {
process.nextTick(function() {
throw new Error("Not handled!");
})
});
}
asyncThrow()
.then(function() {
console.log("resolved");
})
.catch(function() {
console.log("rejected");
});
在此代码执行期间,node.js 存在未经处理的异常(我预计会出现这种行为)。
我也尝试过基于“域”的错误处理:
var Promise = require("promise"); // also tried require("bluebird") here
var domain = require("domain");
function asyncThrow()
{
return new Promise(function(resolve, reject) {
var d = domain.create();
d.on("error", reject);
d.run(function() {
process.nextTick(function() {
throw new Error("Not handled!");
})
});
});
}
asyncThrow()
.then(function() {
console.log("resolved");
},
function() {
console.log("rejected");
})
.catch(function() {
console.log("catch-rejected");
});
此代码行为要好得多,但正如预期的那样 - 调用了“拒绝”函数。
所以问题是:
- 如何在处理异步代码时强制“catch-reject”函数调用?
- 这种方法是否会显着降低性能?
- 您能否提出更好的方法来处理此类异常?
【问题讨论】:
-
为什么要用
process.nextTick()来抛出异常?您在第一个示例中保留了承诺范围。因此它没有被抓住。 -
@Sirko 这是对例如网络交互行为的模拟。当连接丢失时抛出异常。
-
您是否考虑过使用
denodify()也将您的异步调用转换为承诺? -
@Sirko 正如我在 denodify 的源代码中看到的那样,它没有任何魔力 - 它只是一个调用包装器。
-
Promise 库只能捕获在它直接调用的函数或它们直接调用的函数中抛出的异常。没有 Promise 库可以捕获在其他异步回调中引发的异常。因此,当
nextTick()回调中抛出异常时,promise 库无法捕获它。您必须自己捕获它或承诺该特定函数(它将回调替换为 promise 库管理的回调,因此可以捕获异常)。这只是 Javascript 工作方式的现实/限制,也是需要理解的一个重要方面。
标签: javascript node.js exception asynchronous promise