2017-07-21 94 views
0

我從來沒有(有意!)在javascript中使用異步函數。 我必須做一個任務,要求我使用數組元素的異步函數(即for(let i=0;i<array.length;i++){do_Something_Async_here()})在PARALLEL中處理它們。在javascript中爲數組循環創建異步函數?

我一直在使用的setTimeout這樣

unique.forEach(function (number, index) 
    { 
     setTimeout(populateResults(index,number), 0); 
    }); 
function populateResults(index,number) 
{ 
    alert("populating results: index:"+index+" number:"+number); 
    var jp; 
    for(var i=0;i<1000000;i++) 
    { 
     jp=Math.pow(2,100); 
    } 
    alert("results populated: index:"+index+" number:"+number); 
    return jp; 
} 

像這樣

let promises = []; 
for (var i=0;i<unique.length;i++) { 
    promises.push(populateResults(i,unique[i])); 
} 

Promise.all(promises).then(function(results){ 
    console.log(results); 
}).catch(function(err) { 
    // handle error here 
}); 

其實我做的數量和索引的東西試過,但我在這裏簡化它。 現在,當我運行代碼時,在這兩種情況下,似乎我通常在C或java中執行代碼。順序。我錯過了什麼?如何讓他們平行運行? 在此先感謝。

+0

'populateResults'不是一個異步函數,它只是一個普通的函數,所以它會在你把它推入'promises'之前完全執行,儘管它的名字不包含任何promise。用一個返回'Promise'的實際異步函數再試一次,你可能會看到不同的結果。 – Duncan

+0

你嘗試關閉了嗎?例如:https://jsfiddle.net/8n00zre7/ – Kirill

+0

看看SimpleJ的答案在這裏https://stackoverflow.com/questions/24924038/iterate-over-array-running-async-task-on-each-element他使用' setTimeout()' –

回答

0

Javascript中的異步函數是立即返回Promise並在未來某個點完成運行的函數。與C或Java不同,Javascript只是單線程的,所以不要把一個異步函數誤認爲一個在單獨線程中運行的函數:所有的代碼都在同一個線程中運行,因此完全按順序運行。您在異步JavaScript函數中所做的所有工作都會延遲,直到稍後纔開始工作。

這意味着異步函數對於獲取某些遠程數據或超時或在繼續之前等待用戶事件的代碼很有用。如果調用delayedPopulateResults而不是populateResults

function delayedPopulateResults(index, number) { 
    return new Promise(function(resolve) { 
     setTimeout(function() { resolve(populateResults(index, number); }, 
      Math.random()); 
    }); 
} 

現在,您的代碼將創建所有的承諾和完成後記錄結果第二塊:

你可以在這裏使用setTimeout模擬異步函數。但是請記住,所有這些都會在代碼執行之前引入一個隨機延遲:因此,對populateResults()的調用將按隨機順序執行,但仍然需要在下一次運行之前完成每個調用。

如果你可以使用的EcmaScript(ES7)的最新版本,那麼你可以使用asyncawait關鍵字來簡化這一點,但在瀏覽器中運行的代碼,你可能需要使用transpiler如巴貝爾或打字稿,以在ES5中呈現代碼。