0

我想在同步模式下在 node.js 中使用许多包含的循环。

例子 :

for (var i = 0; i < length1; i++) {
  for (var j = 0; j < length2; j++) {
    for (var k = 0; k < length3; k++) {
      //completed 3
    }
    //completed 2
  }
  //do completed 1
}

如何使用异步执行此操作?我试过这个:

exports.myFunction = function (callback) {
  var finalListA = new Array();
  var pos = 0;
  Model_A.find().populate('listOfItems')
    .lean().exec(function (err, As) {
      if (err) {
        console.log(err);
        return callback(err, null);
      } else {
        //For each A
        var i = 0;
        async.whilst(
          function () {
            return i < As.length;
          },
          function (callback1) {
            var isActive = false;
            //For each B into the A
            var j = 0;
            async.whilst(
              function () {
                return j < As[i].Bs.length;
              },
              function (callback2) {
                Model_B.findById(AS[i].Bs[j]._id, function (err, B) {
                  if (err) {} else {
                    var k = 0;
                    // For each C in the B
                    async.whilst(
                      function () {
                        return k < B.Cs.length;
                      },
                      function (callback3) {
                        if (B.Cs[k].dateEnd >= Date.now()) {
                          isActive = true;
                        }
                        k++;
                        callback3();
                      },
                      function (err) {
                        console.log("3 COMPLETED");
                      }
                    );
                  }
                });
                j++;
                callback2();
              },
              function (err) {
                console.log("2 COMPLETED");
                if (err) {} else {
                  if (isActive == true) {
                    finalListA[pos] = As[i];
                    pos = pos + 1;
                  }
                }
              }
            );
            i++;
            callback1();
          },
          function (err) {
            console.log("1 COMPLETED");
            if (err) {} else {
              return callback(null, finalListA);
            }
          }
        );
      }
    });
}

跟踪显示我:

  • 完成 2
  • 完成 2
  • 已完成 1
  • 完成 3
  • 完成 3

预期的顺序是:

  • 完成 3
  • 完成 3
  • 完成 2
  • 完成 2
  • 已完成 1
4

2 回答 2

1

我最近创建了一个更简单的抽象,称为wait.for以在同步模式下调用异步函数(基于 Fibers)。它处于早期阶段,但有效。它是在:

https://github.com/luciotato/waitfor

使用wait.for,您可以调用任何标准的 nodejs 异步函数,就好像它是一个同步函数一样。

我不明白你想在你的代码中做什么。也许您可以多解释一下您的代码,或者给出一些数据示例。我不知道 Model_A 或 Model_B 是什么......我猜你的大部分代码,但是......

使用wait.for您的代码可能是:

var wait=require('wait.for');

exports.myFunction = function(callback) {
  //launchs a Fiber
  wait.launchFiber(inAFiber,callback);
}

function inAFiber(callback) {
    var finalListA = new Array();
    var pos = 0;

    var x= Model_A.find().populate('listOfItems').lean();
    As = wait.forMethod(x,"exec");
    //For each A
    for(var i=0;i<As.length;i++){
        var isActive = false;
        //For each B into the A
        for(var j=0; j < As[i].Bs.length;j++){
           var B=wait.forMethod(Model_B,"findById",AS[i].Bs[j]._id);
           // For each C in the B
           for(var k=0; k < B.Cs.length;k++){
              if(B.Cs[k].dateEnd >= Date.now()) {
                  isActive = true;
              }
            }
            console.log("3 COMPLETED");
        }
        console.log("2 COMPLETED");
        if(isActive == true) {
            finalListA[pos] = As[i];
            pos = pos + 1;
        }
    };
    console.log("1 COMPLETED");
    return callback(null,finalListA);
}

另外,就我所见,您应该在找到一项(isActive)后立即中断循环,并且不需要 var pos。这样做你的代码将是:

var wait=require('wait.for');

exports.myFunction = function(callback) {
  //launchs a Fiber
  wait.launchFiber(inAFiber,callback);
}

function inAFiber(callback) {
    var finalListA = [];

    var x= Model_A.find().populate('listOfItems').lean();
    As = wait.forMethod(x,"exec");
    var isActive;
    //For each A
    for(var i=0;i<As.length;i++){
        isActive = false;
        //For each B into the A
        for(var j=0; j < As[i].Bs.length;j++){
           var B=wait.forMethod(Model_B,"findById",AS[i].Bs[j]._id);
           // For each C in the B
           for(var k=0; k < B.Cs.length;k++){
              if(B.Cs[k].dateEnd >= Date.now()) {
                  isActive = true;
                  break;//for each C
              }
            } //loop for each C

            console.log("3 COMPLETED");
            if (isActive) break;//for each B

        } //loop for each B
        if (isActive) finalListA.push(As[i]);
        console.log("2 COMPLETED");
    } //loop for each A
    console.log("1 COMPLETED");
    return callback(null,finalListA);
}
于 2013-08-21T06:39:09.933 回答
1

您必须从循环的结束回调调用更高循环的回调whilst(就像您对最外层所做的那样),而不是从刚刚开始下一级迭代callback的主体同步调用它们。whilst

顺便说一句,我不知道你真正想要做什么,但whilst似乎不是迭代数组的最佳选择。使用并行each或串行eachSeries(或它们mapreduce等价物)。

于 2013-08-18T15:02:14.460 回答