【问题标题】:deferred chaining, Node.js and q, one single ErrorHandler for all chain-parts延迟链接,Node.js 和 q,所有链部分的单个 ErrorHandler
【发布时间】:2016-09-30 13:51:28
【问题描述】:

我有这样的设计:

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”。我理解这条链有什么问题吗?

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

【问题讨论】:

  • 您真的应该在您的承诺的每个then(...) 声明中进行响应验证。如果响应不包含预期的内容,那么您将破坏承诺链。
  • 但是每个失败回调都会做同样的事情......调用“onUploadFailed”并将错误传递给拒绝。这在我看来就像代码重复并降低了可读性。我想抛出一个异常而不是拒绝,因为 q-documentation 说“catch”方法捕获了上述链的任何错误。不过好像有点臭
  • 我使用的是 bluebird,所以我不确定,但我认为您应该在所有情况下都返回 deferred.promise。
  • 这成功了!我想知道为什么我没有尝试。谢谢(见下面我的回答)
  • 我认为应该避免使用 Q,以免为时已晚。如果不是承诺,deferred.resolve(42) 会返回什么?

标签: javascript node.js promise q deferred


【解决方案1】:

如果checkData() 位于promise 链的开头,那么它需要像own answer 那样编写,返回一个明确的promise。

在中链中它也可以这样编写,但是中链为您提供了更好的选择来编写什么。

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

  • 抛出而不是返回被拒绝的承诺,
  • 返回数据而不是承诺包装的数据。

因此,提供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. 
}

【讨论】:

    【解决方案2】:

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

    【讨论】:

    • 鉴于函数是同步的,你根本不应该使用延迟。要么使用Q/Q.reject 来创建已履行/拒绝的承诺,要么只使用returnthrow,当checkData 用作then 处理程序时具有相同的效果。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-27
    • 1970-01-01
    • 2021-08-08
    • 1970-01-01
    • 2015-08-05
    相关资源
    最近更新 更多