Q.allSettled 没有返回所有结果

Q.allSettled not returning all the results

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

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

对于数组中的每一项:

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

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

ObjB中设置ObjA.ID并保存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[] 的承诺总数是 4。但是尽管如此,结果数组只包含 1 个项目。

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

有人可以告诉我我做错了什么吗?如果我需要以其他方式处理它?

我找到了一种方法来处理上述情况。但我仍然愿意接受其他方法。

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

然后在 allSettled 处理程序(仅监控 1 个承诺)中,我再次通过再次传递 promises 数组(现在包含 4 个承诺)来调用 Q.allSettled。现在 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
  });
});