延迟链接,Node.js 和 q,一个用于所有链部分的错误处理程序
deferred chaining, Node.js and q, one single ErrorHandler for all chain-parts
我有这样的设计:
var postCommand = function(req, res){
parseForm(req)
.then(checkData)
.then(findCommand)
.then(initializeCommand)
.then(saveToDb)
.then(onUploadSucceeded.bind(this, res))
.fail(onUploadFailed.bind(this, res));
}
then 中的方法可能会被拒绝。我希望在发生拒绝后不会再执行任何操作,但最后一个 .fail.
我的 "checkData" 看起来像这样(是的,它是链中唯一的同步部分):
var checkData = function(args){
var deferred = q.defer();
var fields = args[0];
var files = args[1];
var file = args[1].uploadedFile0;
var secondFile = args[1].uploadedFile1;
if(file.type !== "application/javascript"){
return deferred.reject("please only upload javascript-files");
}
(...)
return deferred.resolve([fields, file]);
}
即使在调用 deferred.reject 时,我也会在 "findCommand" 中结束而没有传递参数。我是不是理解这个链条有问题?
还有一个问题:这个设计好吗?或者是否有 other/better 最佳实践?
正如 Keith 在他的评论中所建议的那样,这是一个语法问题,解决方案:
var checkData = function(args){
var deferred = q.defer();
var fields = args[0];
var files = args[1];
var file = args[1].uploadedFile0;
var secondFile = args[1].uploadedFile1;
if(file.type !== "application/javascript"){
deferred.reject("please only upload javascript-files");
}
else{
deferred.resolve([fields, file]);
}
return deferred.promise;
}
如果 checkData()
位于承诺链的开头,那么它需要像您的 那样编写,return 是一个明确的承诺。
在 mid-chain 中,它也可以像这样写,但是 mid-chain 为您提供了更好的选择来写什么。
更具体地说,您可以通过以下方式避免创建和 return 承诺:
- 抛出而不是 return拒绝承诺,
- return处理数据而不是承诺包装的数据。
因此,如果 checkData()
从未在其他地方用于启动承诺链,则可以这样写:
var checkData = function(args) {
var fields = args[0],
files = args[1],
file = args[1].uploadedFile0,
secondFile = args[1].uploadedFile1;
if(file.type !== "application/javascript") {
throw new Error("please only upload javascript-files"); // always throw an Error object, thus emulating a natural Error. This error will percolate down to the `.fail(onUploadFailed.bind(this, res))` handler.
}
(...)
return [fields, file]; // the next step in the chain will assimilate a promise or data.
}
我有这样的设计:
var postCommand = function(req, res){
parseForm(req)
.then(checkData)
.then(findCommand)
.then(initializeCommand)
.then(saveToDb)
.then(onUploadSucceeded.bind(this, res))
.fail(onUploadFailed.bind(this, res));
}
then 中的方法可能会被拒绝。我希望在发生拒绝后不会再执行任何操作,但最后一个 .fail.
我的 "checkData" 看起来像这样(是的,它是链中唯一的同步部分):
var checkData = function(args){
var deferred = q.defer();
var fields = args[0];
var files = args[1];
var file = args[1].uploadedFile0;
var secondFile = args[1].uploadedFile1;
if(file.type !== "application/javascript"){
return deferred.reject("please only upload javascript-files");
}
(...)
return deferred.resolve([fields, file]);
}
即使在调用 deferred.reject 时,我也会在 "findCommand" 中结束而没有传递参数。我是不是理解这个链条有问题?
还有一个问题:这个设计好吗?或者是否有 other/better 最佳实践?
正如 Keith 在他的评论中所建议的那样,这是一个语法问题,解决方案:
var checkData = function(args){
var deferred = q.defer();
var fields = args[0];
var files = args[1];
var file = args[1].uploadedFile0;
var secondFile = args[1].uploadedFile1;
if(file.type !== "application/javascript"){
deferred.reject("please only upload javascript-files");
}
else{
deferred.resolve([fields, file]);
}
return deferred.promise;
}
如果 checkData()
位于承诺链的开头,那么它需要像您的
在 mid-chain 中,它也可以像这样写,但是 mid-chain 为您提供了更好的选择来写什么。
更具体地说,您可以通过以下方式避免创建和 return 承诺:
- 抛出而不是 return拒绝承诺,
- return处理数据而不是承诺包装的数据。
因此,如果 checkData()
从未在其他地方用于启动承诺链,则可以这样写:
var checkData = function(args) {
var fields = args[0],
files = args[1],
file = args[1].uploadedFile0,
secondFile = args[1].uploadedFile1;
if(file.type !== "application/javascript") {
throw new Error("please only upload javascript-files"); // always throw an Error object, thus emulating a natural Error. This error will percolate down to the `.fail(onUploadFailed.bind(this, res))` handler.
}
(...)
return [fields, file]; // the next step in the chain will assimilate a promise or data.
}