我刚刚开始在es6中探索async/await
,我发现一些让我感到惊讶的事情。基本上,forEach
行为异步,而for
循环同步行为就是示例
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)
})
我知道for
和forEach
版本应同步运行,在这种情况下,forEach
如何变为异步?
答案 0 :(得分:1)
考虑Promsies(这是async / await真的是什么)
在他第一个案例中,你正在链接承诺,就像你会做的那样
forEach
在第二种情况下,您只是立即调用所有承诺,因为data.forEach(x => getData(x).then(val => console.log(...)));
会立即运行并按照您的意愿注册所有承诺:
const res = await Promise.all(data.map(item => getData(item)));
注意,在这种情况下,getData(1)实际上并不等待getData(0)完成 - 没有链接。你在forEach中等待,然后在每个promises中链接一个,只捕获仍在forEach中的下一段代码
这意味着在第二种情况下,这些承诺将相互异步运行。
如果你确实想要这个,但是你想等待所有的调用完成(使用第二种方法)你只需要一个Promise.all + map方法:
forEach
这将有效地将getData的所有结果放在结果数组中数组中的每个项目上,但请记住这些调用都是异步的。
此外,无法使用标准reduce
使函数等待彼此。您可以使用await data.reduce((intermPromise, item) => intermPromise.then(getData(item)), Promise.resolve());
操作,而不是:
map
这基本上通过减少数组来链接对每个项目的调用,从单元Promise开始。最终等待在外面将适用于与所有呼叫链接的最终承诺。
另请注意使用reduce
方法之间的区别 - 您实际上很容易获得数组中的所有结果(但它运行异步) - 以及albumTable.setColumnResizePolicy ( TableView.CONSTRAINED_RESIZE_POLICY );
artistColumn.prefWidthProperty().bind(albumTable.widthProperty().multiply(0.4));
yearColumn.prefWidthProperty().bind(albumTable.widthProperty().multiply(0.2));
albumColumn.prefWidthProperty().bind(albumTable.widthProperty().multiply(0.4));
artistColumn.setResizable(false);
yearColumn.setResizable(false);
albumColumn.setResizable(false);
方法 - 您可以获得同步调用,但最终结果不会返回一个数组,实际上它只返回最后一次调用的结果。
希望这有帮助。