2017-05-04 61 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方法 - - 在这里你实际上得到一个数组轻松所有结果(但它运行异步),你在哪里得到同步调用,但最终的结果将不会返回一个数组,实际上它只会返回最后一次调用的结果。

希望这会有所帮助。