Javascript 延迟链接,Node.js和q,一个用于所有链部件的错误处理程序

Javascript 延迟链接,Node.js和q,一个用于所有链部件的错误处理程序,javascript,node.js,promise,q,deferred,Javascript,Node.js,Promise,Q,Deferred,我有一个这样的设计: var postCommand = function(req, res){ parseForm(req) .then(checkData) .then(findCommand) .then(initializeCommand) .then(saveToDb) .then(onUploadSucceeded.bind(this, res)) .fail(onUploadFailed.bind(this, re

我有一个这样的设计:

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中的方法可能会拒绝。我希望在拒绝发生后,除了最后一次。失败之外,不会再执行任何操作

我的“checkData”如下所示(是的,它是链中唯一的同步部分):

即使在调用deferred.reject时,我也会在“findCommand”中结束,而不传递参数。我理解这个链条有什么问题吗


还有一个问题:这种设计是一种好的模式吗?还是有其他/更好的最佳实践?

正如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;
}

正如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()
位于承诺链的开头,则需要像在中一样编写它,返回一个明确的承诺

在中链中,当这样写的时候它也会工作,但是中链在写什么上给了你更好的选择

更具体地说,您可以通过以下方式避免创建和返回承诺:

  • 扔掉而不是退回被拒绝的承诺
  • 返回数据而不是承诺包装的数据
因此,如果在别处从未使用
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. 
}
如果
checkData()
位于承诺链的开头,则需要像在中一样编写它,返回一个明确的承诺

在中链中,当这样写的时候它也会工作,但是中链在写什么上给了你更好的选择

更具体地说,您可以通过以下方式避免创建和返回承诺:

  • 扔掉而不是退回被拒绝的承诺
  • 返回数据而不是承诺包装的数据
因此,如果在别处从未使用
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. 
}

您真的应该在每个
声明中进行响应验证,然后(…)
声明您的承诺。如果响应不包含预期的内容,那么您就破坏了承诺链。但是每个失败回调都会这样做。。。调用“onUploadFailed”,并将错误传递给拒绝。在我看来,这就像代码复制,降低了可读性。我想抛出一个exeption,而不是拒绝,因为q文档中说“catch”方法捕获上述链中的任何错误。但这似乎有点臭,我用蓝鸟,所以我不确定,但我认为你应该推迟返回。承诺在所有情况下。这是有效的!我不知道我为什么不试一下。谢谢你(见下面我的答案),我相信在为时已晚之前应该避免问。如果不是承诺,那么什么是延迟的。解决(42)返回?您应该在每个
承诺声明中进行响应验证,然后(…)
声明。如果响应不包含预期的内容,那么您就破坏了承诺链。但是每个失败回调都会这样做。。。调用“onUploadFailed”,并将错误传递给拒绝。在我看来,这就像代码复制,降低了可读性。我想抛出一个exeption,而不是拒绝,因为q文档中说“catch”方法捕获上述链中的任何错误。但这似乎有点臭,我用蓝鸟,所以我不确定,但我认为你应该推迟返回。承诺在所有情况下。这是有效的!我不知道我为什么不试一下。谢谢你(见下面我的答案),我相信在为时已晚之前应该避免问。如果不是一个承诺,
deferred.resolve(42)
将返回什么?鉴于函数是同步的,您根本不应该使用deferreds。使用
Q
/
Q.reject
创建已履行/拒绝的承诺,或者只使用
return
throw
,当
checkData
用作
then
处理程序时具有相同的效果。鉴于函数是同步的,您根本不应该使用延迟。使用
Q
/
Q.reject
创建已履行/已拒绝的承诺,或者只使用
返回
抛出
,这与
检查数据
用作
然后
处理程序时具有相同的效果。