2014-07-04 100 views
0

我想執行一個for-loop結構內的異步方法,然後顯示結果。我相信問題是在cryto.randomBytes方法調用回調之前,for-loop增量。我將如何正確執行這個for循環?如何正確執行for循環內的異步方法?

var crypto = require('crypto'); 
var nimble = require('nimble'); 

var codes = []; 

nimble.series([ 
function(callback){ 

    for(var i = 0; i < 100;i++){ 

     crypto.randomBytes(64, function(ex, buf) { 
      if (ex) throw ex; 
      codes[i] = buf.toString('hex'); 
     }); 

    } 

    callback(); 

}, 
function(callback){ 

    for(var i = 0; i < codes.length;i++){ 
     console.log("Ticket " + i + ":" + codes[i]); 
    } 

    callback(); 

}]); 

回答

2

是的,你說得對,循環在調用回調之前完成。您可以使用匿名函數來創建一個範圍,其中每個迭代都獲取自己的變量副本。

而且,你會調用回調後的最後一個值已經被添加到結果,在循環之後沒有:

function(callback){ 

    var cnt = 0; 
    for(var i = 0; i < 100;i++){ 
    (function(i){ 
     crypto.randomBytes(64, function(ex, buf) { 
      if (ex) throw ex; 
      codes[i] = buf.toString('hex'); 
      if (++cnt == 100) { 
      callback(); 
      } 
     }); 
    })(i); 
    } 

} 
+0

很多不必要的關閉在這裏創建。 – mscdex

+0

@mscdex:這可能可以簡化,因爲在這種特殊情況下,這些值是隨機的,所以它們在數組中的最終順序應該沒有關係。除非不同的數字需要不同的時間才能生成,所以它實際上引入了隨機數的可預測性,在這種情況下,它將大大降低隨機生成器的強度。 – Guffa

+0

後者中的任何一個與創建閉包有什麼關係? – mscdex

2

相反的:

function(callback){ 

    for(var i = 0; i < 100;i++){ 

     crypto.randomBytes(64, function(ex, buf) { 
      if (ex) throw ex; 
      codes[i] = buf.toString('hex'); 
     }); 

    } 

    callback(); 

}, 

你可以嘗試這樣的:

function(callback){ 

    for(var i = 0, len = 100; i < len; i++){ 

     crypto.randomBytes(64, function(ex, buf) { 
      if (ex) throw ex; 
      codes.push(buf.toString('hex')); 
      if (codes.length === len) 
       callback(); 
     }); 

    } 

}, 
1

使用具有遞歸性的IIFE應該可以工作:

var crypto = require('crypto'); 
var nimble = require('nimble'); 

var codes = []; 

nimble.series([ 

function (callback) { 

    // Using an IIFE 
    (function recursive(index) { 

     if (index < 100) { // i < 100 
      crypto.randomBytes(64, function (ex, buf) { 
       if (ex) throw ex; 
       codes[index] = buf.toString('hex'); 
       recursive(index + 1); 
      }); 
     } else callback(); 

    })(0); // i = 0 

}, 

function (callback) { 

    for (var i = 0; i < codes.length; i++) { 
     console.log("Ticket " + i + ":" + codes[i]); 
    } 

    callback(); 

}]);