Q.allSettled没有返回所有结果

时间:2016-01-19 18:19:03

标签: node.js pseudocode q loopbackjs

我正在尝试在NodeJS(LoopbackJS)中使用Q.allSettled来实现以下场景。

作为我的方法(REST API)的输入,我得到了一个对象数组。这些对象中的每一个在内部都有两个对象:ObjA& ObjB

对于数组中的每个项目:

如果数据库中存在ObjA,请获取其ID并发送邮件#1

如果它不存在,则插入ObjA然后获取其ID并发送邮件#2。

ObjA.ID中设置ObjB并保存ObjB

保存所有对象并发送电子邮件后,发送REST API电话的响应。如果以前的任何任务失败,请在响应中添加错误详细信息。

以下是伪代码

myModel.myMethod = function(input, cb){
  var defResp = Q.defer();
  var promises = [];
  try {
    var defObjAList = Q.defer();
    promises.push(defObjAList.promise);

    getObjAIfItExists(input).done(function(inputWIds) { // input[] with IDs populated
      inputWIds.forEach(function(item){
        var defObjA = Q.defer();

        if(item.objA.id){ // objA already exists in DB
          var options = { ... }; // options for sending mail #1
          promises.push(Q.ninvoke(Email, "send", options)); // using loopback Email which internally uses nodemailer
          defObjA.resolve(item.objA.id);
        } else {
          Q.ninvoke(ObjA, "save", item.objA).done(function (savedA) {
            var options = { ... }; // options for sending mail #2
            promises.push(Q.ninvoke(Email, "send", options)); // using loopback Email which internally uses nodemailer
            console.log(promises.length); // prints 3
            defObjA.resolve(savedA.id);
          }, function(err){
            defResp.reject(err);
          });
        }

        var defObjB = Q.defer();
        promises.push(defObjB.promise);

        defObjA.promise.done(function(objAId){
          item.objB.objAId = objAId;
          promises.push(Q.ninvoke(ObjB, "save", item.objB));
          console.log(promises.length); // prints 4
        }, function(err){
          defResp.reject(err);
        });

        console.log(promises.length); // prints 2
        defObjAList.resolve("Process Complete");
      }); // inputWIds.forEach
    }, function(err){
      defResp.reject(err);
    }); //getObjAIfItExists

    console.log(promises.length); // prints 1
    Q.allSettled(promises).done(function (results) {
      console.log(results.length); // prints 1
      console.log(JSON.stringify(results)); // prints result[] with single item
      var response = {};
      response.errors = [];
      // iterate on results and check if any promise was failed, if yes add the reason to errors array
      defResp.resolve(response);
    });

  } catch (err) {
    defResp.reject(err);
  }
  return defResp.promise.nodeify(cb);
}

出于测试目的,我的输入数组只包含一个项目。因此,添加到promises[]的promises总数为4.但是尽管如此,结果数组只包含1个项目。

我的代码适用于正常情况,但如果出现错误,例如在发送邮件时,我需要发送邮件作为回应。这是行不通的,因为结果数组不包含电子邮件发送承诺的输出。

有人能告诉我我做错了什么吗?如果我需要以其他方式处理它?<​​/ p>

1 个答案:

答案 0 :(得分:0)

我找到了处理上述情况的方法。但我仍然愿意接受替代方法。

在向defObjAList数组添加第二个承诺后,我没有解析promises,而是等到所有承诺都添加到数组中。

然后在allSettled处理程序(仅监视1个promise)中,我再次通过传递Q.allSettled数组(现在包含4个promise)来调用promises。现在,allSettled的第二个处理程序获取结果数组,其中包含4个项目,用于添加的所有承诺。

或者,我可以简单地等待defObjAList承诺履行,然后致电Q.allSettled以了解其余的承诺。这在性能方面会更好。但目前我已拨打2次电话Q.allSettled

  :
  :
  inputWIds.forEach(function(item, ind){ // added ind param

    // handle ObjA

    var defObjB = Q.defer();
    promises.push(defObjB.promise);

    defObjA.promise.done(function(objAId){
      item.objB.objAId = objAId;
      promises.push(Q.ninvoke(ObjB, "save", item.objB));
      console.log(promises.length); // prints 4
      if(ind == inputWIds.length-1){ // check if its the last iteration
        defObjAList.resolve("Process Complete");
      }
    }, function(err){
      defResp.reject(err);
    });

    console.log(promises.length); // prints 2
    // defObjAList.resolve("Process Complete"); - removed from here
  }); // inputWIds.forEach

  :
  :

Q.allSettled(promises).done(function (resultsOld) {
  Q.allSettled(promises).done(function (results) {
    console.log(results.length); // prints 4
    // handle results array and send response
  });
});