与正常循环

时间:2017-05-04 05:45:38

标签: javascript asynchronous ecmascript-6 promise

我刚刚开始在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)
})

我知道forforEach版本应同步运行,在这种情况下,forEach如何变为异步?

1 个答案:

答案 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); 方法 - 您可以获得同步调用,但最终结果不会返回一个数组,实际上它只返回最后一次调用的结果。

希望这有帮助。