我正在使用此代码将经典的 nodejs 函数转换为 promise 函数:
Object.defineProperty(Function.prototype, "toPromise", {
enumerable: false,
configurable: false,
writable: false,
value: function(self) {
var $this;
$this = this;
return function() {
var arg, args, deferred, _i, _len;
deferred = Q.defer();
args = [];
for (_i = 0, _len = arguments.length; _i < _len; _i++) {
arg = arguments[_i];
args.push(arg);
}
args.push(function() {
args = Array.prototype.slice.call(arguments);
if (args[0] instanceof Error) {
return deferred.reject.apply($this, args);
} else {
return deferred.resolve.apply($this, args);
}
});
$this.apply(self, args);
return deferred.promise;
};
}
});
然后我在一个函数上调用它以获取另一个函数。像那样:
exports.list = (function(userid, options, callback) {
// do something
// success ->
callback(data);
// error ->
callback(err)
}).toPromise(this);
但是当抛出不是我抛出的异常(SyntaxError、TypeError...)时,then
或 fail
函数不是叫。如何自动传播?
我试图用它替换 toPromise 但这没有用(即使它正在使用我的函数)
Object.defineProperty(Function.prototype, "toPromise", {
enumerable: false,
configurable: false,
writable: false,
value: function(self) {
var $this;
$this = this;
return Q.denodeify(this.bind(Kitty));
}
});
我还尝试对 then
应用第二个回调,但我也没有成功。
最佳答案
But when an exception that wasn't thrown by me (SyntaxError, TypeError...) is thrown, the then or fail function isn't called.
Q
只捕获从 .then()
回调中抛出的异常。您需要自己明确处理所有其他异常。
How to propagate it automatically?
如果异常是从您自己的代码中抛出的,您可以考虑在较低级别使用 Promises,并将您自己的代码仅放在 then
回调中。
如果异常是从您调用的“经典 nodejs 函数”中抛出的,您将需要捕获
它。但是,抛出异常(这是相当不可恢复的)而不是仅仅使用错误参数调用回调可能有充分的理由,这将是异步 Node 函数的“正常”设计方法。
如果你想在你的 toPromise
方法中包含这样的功能,它需要包装函数调用:
try {
$this.apply(self, args);
} catch(e) {
deferred.resolve(e);
}
(function(…, callback) { … }).toPromise(this);
这是个坏主意。你不应该在你自己的函数上使用 toPromise
,而应该只在那些给你的并且有非 promise 接口(interface)的函数上使用。参见 The Beginning在教程部分如何提出一个真正返回 Promise 的函数。不要使用 callback
变量。一些错误很容易让你逃脱。特别是如果你有一个已经产生 promise 的函数,你需要做的就是在它之后链接其他任务。
在您的具体情况下,这很简单
exports.list = function(userid, options) {
return canThis(userid, "mod", "browse").then(function(can) {
if (can === false)
throw error.throwError("Forbidden", "UNAUTHORIZED");
if (options.perPage > 50) {
throw error.throwError("Too much mods per page", "INVALID_PARAMS");
var Mod = mongoose.model("Mod");
return Q.all([ // I would assume that listing and counting can happen in parallel?
Q.ninvoke(Mod, "list", options),
Q.ninvoke(Mod.count(), "exec")
]).spread(function(mods, count) {
mods.totalCount = count;
return mods;
}, function(err) { // and throw this error when one happens in either?
throw error.throwError(err, "DATABASE_ERROR");
// not sure whether you need errors.handleResult at all
// (not with a callback, at least)
});
});
};
现在所有这些 return
实际上都有意义了。
关于javascript - Q promise 传播错误和异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23410273/