2013-08-18 94 views
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
+0

你吃过看看子进程http://nodejs.org/api/child_process.html – sbarow

+2

不,我不明白孩子过程中对我的问题的兴趣? – ChrisD

回答

1

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

顺便说一句,我不知道你真的想做什么,但whilst似乎不是迭代阵列的最佳选择。使用并行each或串行eachSeries(或其等效的mapreduce)。

1

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

https://github.com/luciotato/waitfor

使用wait.for,你可以调用任何标准异步的NodeJS功能,就好像它是一个同步功能。

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

使用wait.for代码migth是:

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