通过在循环上使用await,等待循环完成

时间:2018-12-12 16:24:23

标签: javascript node.js async-await

js循环中的同步性仍在推动我前进。

我想做的很简单

async doAllTheThings(data, array) {
    await array.forEach(entry => {
        let val = //some algorithm using entry keys
        let subVal = someFunc(/*more entry keys*/)
        data[entry.Namekey] = `${val}/${subVal}`;
    });
    return data; //after data is modified
}

但是我不能确定那是否真正安全。我只是不喜欢简单的循环模式

for (i=0; i<arrayLength; i++) {
    //do things
    if (i === arrayLength-1) {
        return
    }
}

我想要一种更好的方法,但是我无法确定我正在尝试的内容是否安全运行,或者我只是没有找到会触发竞争条件的数据模式。

或者我想得太多了。数组中的算法仅由一些MATH和赋值语句组成...以及一个小的函数调用,其本身也仅由更多MATH和赋值语句组成。据说这些都是全面同步的。但是循环有时很奇怪。

问题

您可以在循环本身之外使用await来触发代码以等待循环完成吗?或者,这是唯一的安全方法,可以通过只检查循环中的位置,然后手动返回终点,直到返回终点,这才是老方法。

2 个答案:

答案 0 :(得分:0)

处理异步和循环的最好方法之一是放一个诺言,然后等待Promise。所有人都记住await返回一个Promise,所以您可以这样做:

async function doAllTheThings(array) {
    const promises = []
    array.forEach((entry, index) => {
        promises.push(new Promise((resolve) => {
            setTimeout(() => resolve(entry + 1), 200 )
        }))
    });
    return Promise.all(promises)
}

async function main () {

    const arrayPlus1 = await doAllTheThings([1,2,3,4,5])
    console.log(arrayPlus1.join(', '))
}
main().then(() => {
    console.log('Done the async')
}).catch((err) => console.log(err))

另一种选择是使用generators,但它们要复杂一些,因此,如果您可以保存诺言并等待,那么这是一种更简单的方法。

最后的问题:

  

您可以在循环本身之外使用await来触发代码以等待循环完成吗?或者,这是唯一的安全方法,可以通过只检查循环中的位置,然后手动返回终点,直到返回终点,这才是老方法。

所有javascript循环都是同步的,因此下一行将等待循环执行。

如果您需要循环执行一些异步代码,则上述的promise方法是一种很好的方法。

异步循环的另一种方法是迭代器/生成器方法,特别是在必须“暂停”或从循环外部获取信息的情况下。

答案 1 :(得分:-1)

仅当您执行网络或I / O操作(发出网络请求,写入文件等)时,才需要进行异步等待(或承诺,在后台进行相同的操作)。

在循环中,您无需承诺,代码将同步执行。