【问题标题】:How to call Q promise notify within the promise chain如何在 Promise 链中调用 Q Promise notify
【发布时间】:2014-05-26 16:56:51
【问题描述】:

我需要有关承诺链中 notify() 的帮助。

我有 3 个 promise 基函数 connect()send(cmd)disconnect()。现在我想编写另一个函数来用进度通知以下列方式包装这些调用。

function bombard() {
 return connect()
  .then(function () {
    var cmds = [/*many commands in string*/];
    var promises = _.map(cmds, function (cmd) {
     var deferred = Q.defer();
     deferred.notify(cmd);
     send(cmd).then(function (result) {
      deferred.resovle(result);
     });
     return deferred.promise;
    });
    return Q.all(promises);
  })
 .finally(function () { return disconnect() })
}

这样运行函数

bombard.then(onResolve, onReject, function (obj) {
 console.log(ob);
});

我想我会收到我发送的每个命令的通知。但是,它并没有像我预期的那样工作。我实际上什么都得不到。

虽然我相信这是由于这些通知没有传播到外部承诺,但我不知道如何在 Q 上传播这些通知或包装承诺链:connectsenddisconnect in一个延迟对象。

谢谢

【问题讨论】:

    标签: javascript promise q


    【解决方案1】:

    我有一些好消息和一些坏消息。

    非常好!您已经发现了通知 API 的问题,以及为什么它在 v2 分支的 Q 中被删除,在 Bluebird 等较新的库中被弃用,并且从未包含在 ECMAScript 6 中。这真的归结为承诺不是事件发射器的事实.

    通知 API 不能很好地组合或聚合。事实上,在 imo 开始时,关于 promise 的通知并没有太大意义。

    相反,我建议甚至使用进度通知,有点像 C# 中的 IProgress。我将使用Q.delay() 模拟所有操作以进行隔离,您的代码显然会进行真正的调用

    function connect(iProgress){
        return Q.delay(1000).then(function(res){
            iProgress(0.5,"Connecting to Database");
        }).delay(1000).then(function(res){
            iProgress(0.5,"Done Connecting");
        });
    
    } 
    
    function send(data,iProgress){
         return Q.delay(200*Math.random() + 200).then(function(res){
             iProgress(0.33, "Sent First Element");
         }).delay(200*Math.random() + 400).then(function(){
             iProgress(0.33, "Sent second Element");
         }).delay(200*Math.random() + 500).then(function(){
             iProgress(0.33, "Done sending!");
         });
    }
    // disconnect is similar
    

    现在,我们可以轻松决定我们的 Promise 是如何构成的,例如:

    function aggregateProgress(num){
         var total = 0;
         return function(progression,message){
              total += progression;
              console.log("Progressed ", ((total/num)*100).toFixed(2)+"%" );
              console.log("Got message",message);
         }
    }
    

    这会让你做什么:

    // bombard can accept iProgress itself if it needs to propagate it
    function bombard() {
     var notify = aggregateProgress(cmds.length+1);
     return connect(notify)
      .then(function () {
        var cmds = [/*many commands in string*/];
        return Q.all(cmds.map(function(command){ return send(command,notify); }));
      });
    }
    

    Here is a complete and working fiddle to play with

    【讨论】:

    • 非常感谢。很遗憾听到我们需要一种解决方法来获得通知。
    • @MondWan 这实际上不是一种解决方法,实际上它比进程.then hack 干净得多。
    • +1 表示“承诺不是事件发射器”评论。我现在正在更改我的代码...
    猜你喜欢
    • 1970-01-01
    • 2015-01-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-26
    • 2018-02-06
    • 2013-08-02
    • 2018-01-07
    相关资源
    最近更新 更多