2017-05-04 69 views
0

我剛開始探索ES6 async/await,我發現一些真正的驚喜me.Basically,forEach表現異步而for循環表現同步這裏例如陣列在foreach是異步比較正常的循環

function getData(d) { 
    return new Promise((resolve,reject)=>{ 
     setTimeout(()=>{ 
      resolve(d.x+" %%%% ") 
     },1000) 
    }) 
} 
const data=[{x:"aaa"},{x:"bbb"}] 


//async for loop 
const makeRequest1 = async() => { 
    for (let i in data){ 
     let value=data[i] 
     console.log(value) 
     value.p=await getData(value) 
     console.log(JSON.stringify(value)+ ' after') 
    } 
    // console.log(rr) 
    console.log(data) 
    console.log("Is it block ??") 
    return "done" 
} 
// { x: 'aaa' } 
// {"x":"aaa","p":"aaa %%%% "} after 
// { x: 'bbb' } 
// {"x":"bbb","p":"bbb %%%% "} after 
// [ { x: 'aaa', p: 'aaa %%%% ' }, { x: 'bbb', p: 'bbb %%%% ' } ] 
// Is it block ?? 
//  done 



//async for loop 
const makeRequest2 = async() => { 
    data.forEach(async (value)=>{ 
     console.log(value) 
     value.p=await getData(value) 
     console.log(JSON.stringify(value)+ ' after') 
    }) 
    console.log(data) 
    console.log("Is it block ??") 
    return "done" 
} 
// { x: 'aaa' } 
// { x: 'bbb' } 
// [ { x: 'aaa' }, { x: 'bbb' } ] 
// Is it block ?? 
// done 
// {"x":"aaa","p":"aaa %%%% "} after 
// {"x":"bbb","p":"bbb %%%% "} after 


makeRequest2().then((r)=>{ 
    console.log(r) 
}) 

我知道forforEach版本應該同步運行,在這種情況下forEach怎麼會變成異步?

+3

也許是因爲在回調前的'async' ... – Weedoze

+0

@Weedoze很有可能,是否有任何詳細的解釋 – Guigui

+1

您是說您正在探索'async'和'await',然後閱讀文檔。這會給你解釋 – Weedoze

回答

1

想想Promsies方面(這是異步/等待真的是)

詮釋,他的第一個情況下,你要鏈接的承諾,就像你會做

getData(data[0]) 
    .then((val) => console.log(...)) 
    .then(() => getData(data[1]) 
    .then(... 

在第二種情況下,你「再打電話只是所有承諾一次,因爲forEach運行瞬間並註冊那些許諾,你會:

data.forEach(x => getData(x).then(val => console.log(...))); 

注意,在這種情況下的getData(1)d實際上並不等待getData(0)完成 - 沒有鏈接。您在forEach內部的等待只是在每個承諾中鏈接一個,然後只捕獲仍在forEach內的下一段代碼

這意味着這些承諾將在第二種情況下相互之間異步運行。

如果你確實想這一點,但要等待所有的調用來完成(使用第二種方法),你只需要一個Promise.all +地圖的方法:

const res = await Promise.all(data.map(item => getData(item))); 

這將有效將結果數組中的每個項目中的每個項目的getData結果都帶上,但請記住這些調用都是異步的。

此外,沒有辦法使用標準forEach來使該函數等待彼此。你可以使用一個reduce操作,而不是這樣:

await data.reduce((intermPromise, item) => intermPromise.then(getData(item)), Promise.resolve()); 

這基本上通過減少陣列,從一個單元無極鏈的每個項目的呼籲。外面最後的等待將用於與所有呼叫鏈接的最終承諾。

還要注意使用map方法之間的差異 - 和reduce方法 - - 在這裏你實際上得到一個數組輕鬆所有結果(但它運行異步),你在哪裏得到同步調用,但最終的結果將不會返回一個數組,實際上它只會返回最後一次調用的結果。

希望這會有所幫助。