2016-07-14 70 views
0

我在一個循環取結果並推到一個這樣的數組有一個異步操作:如何正確地等待在同步循環觸發的所有異步函數返回一個值 - JS

arr = [] 
 

 
while (some_limit_reaches) { 
 
    async_operation(arg, function(err, data) { 
 
    if (!err) 
 
    arr.push(data) 
 
    }) 
 
} 
 

 
// now arr is not completely filled until all async 
 
// operations are finished in the loop above

問題是數組沒有完全填充,直到完成所有的異步操作,如何在循環結束後使用完全填充的數組而不使用setTimeout?

+0

如果您發現我的答案有用,您會考慮投票/接受我的答案嗎?謝謝。 – morels

回答

0

您正試圖使異步操作同步。您需要檢查您的異步回調中您的期望狀態是否爲真。嘗試這樣的事情。

while (some_limit_reaches) { 
    async_operation(arg, function(err, data) { 
    if (!err) 
    arr.push(data); 
    if(check_if_the_array_is_full){ 
     //Call some function that continues your operation 
    } 
    }) 
} 

這樣你的處理將不會繼續,直到所有的數組已滿。

0

該解決方案有點冗長,但尊重任務的分離。其模式類似於kriskowal的q.all

var arr = [], limit = 10, i=0, terminated_operations = 0; 

while (i < limit) { 
    async_operation(arg, function(err, data) { 
    if (!err) { 
    arr.push(data); 
    operationTerminated(arr); 
    } 
    }); 
} 

function operationTerminated(data) { 
    terminated_operations++; 
    if(terminated_operations === limit - 1) { 
    doStuff(data); 
      terminated_operations = 0; 
    } 
} 

function doStuff(data) { 
    console.log('all data returned', data); 
} 

第一個代碼段代表了核心邏輯。第二個函數只是第三個函數聲明的觸發器。

編輯:

爲了在標題原來的問題回答

我怎樣才能確保異步操作不保留在我的代碼陣列是空的?

我建議在async_operation失敗的情況下返回data=undefined,所以你可以接受也[]作爲有效的返回值,並保持在覈心邏輯較高的控制。通過這種方式,您可以將環路重寫爲:

while (i < limit) { 
    async_operation(arg, function(err, data) { 
    if(err) { 
    console.error('error occurred', err); 
    break; 
    } 
    if(data) { 
    arr.push(data); 
    operationTerminated(arr); 
    } 
    }); 
}