简体   繁体   English

通过在循环上使用await等待循环结束

[英]Waiting for loops to finish by using await on the loop

Synchronicity in js loops is still driving me up the wall. js循环中的同步性仍在推动我前进。

What I want to do is fairly simple 我想做的很简单

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
}

But I can't tell if that's actually safe or not. 但是我不能确定那是否真正安全。 I simply don't like the simple loop pattern 我只是不喜欢简单的循环模式

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

I wanted a better way to do it, but I can't tell if what I'm trying is working safely or not, or I simply haven't hit a data pattern that will trigger the race condition. 我想要一种更好的方法来执行此操作,但是我无法确定我正在尝试的内容是否安全运行,或者我只是没有找到会触发竞争条件的数据模式。

Or perhaps I'm overthinking it. 也许我想得太多。 The algorithm in the array consists solely of some MATH and assignment statements...and a small function call that itself also consists solely of more MATH and assignment statements. 数组中的算法仅由一些MATH和赋值语句组成...以及一个小的函数调用,其本身也仅由更多MATH和赋值语句组成。 Those are supposedly fully synchronous across the board. 据说这些都是全面同步的。 But loops are weird sometimes. 但是有时候循环很奇怪。

The Question 问题

Can you use await in that manner, outside the loop itself, to trigger the code to wait for the loop to complete? 您是否可以在循环本身之外使用await来触发代码以等待循环完成? Or is the only safe way to accomplish this the older manner of simply checking where you are in the loop, and not returning until you hit the end, manually. 或者,这是完成此旧方法的唯一安全方法,该方法只是简单地检查循环中的位置,直到手动结束才返回。

One of the best ways to handle async and loops is to put then on a promise and wait for Promise.all remember that await returns a Promise so you can do: 处理异步和循环的最佳方法之一是放一个Promise并等待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))

Another option is to use generators but they are a little bit more complex so if you can just save your promises and wait for then that is an easier approach. 另一个选择是使用生成器,但是生成器要稍微复杂一些,因此,如果您可以保存承诺并等待,那么这是一种更简单的方法。

About the question at the end: 关于最后的问题:

Can you use await in that manner, outside the loop itself, to trigger the code to wait for the loop to complete? 您是否可以在循环本身之外使用await来触发代码以等待循环完成? Or is the only safe way to accomplish this the older manner of simply checking where you are in the loop, and not returning until you hit the end, manually. 或者,这是完成此旧方法的唯一安全方法,该方法只是简单地检查循环中的位置,直到手动结束才返回。

All javascript loops are synchronous so the next line will wait for the loop to execute. 所有的javascript循环都是同步的,因此下一行将等待循环执行。

If you need to do some async code in loop a good approach is the promise approach above. 如果您需要循环执行一些异步代码,则上述的promise方法是一个好的方法。

Another approach for async loops specially if you have to "pause" or get info from outside the loop is the iterator/generator approach. 特别是在必须“暂停”或从循环外部获取信息的情况下,异步循环的另一种方法是迭代器/生成器方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM