2013-08-18 93 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); 
}