V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
icemanpro
V2EX  ›  Node.js

如何等待 foreach 完成之后才能进行下一步?

  •  
  •   icemanpro · 2020-06-06 11:05:02 +08:00 · 6446 次点击
    这是一个创建于 1629 天前的主题,其中的信息可能已经有所发展或是发生改变。
    foreach 是异步,但在下一步之前,需要得到 foreach 的完成数据。应该如何处理?
    24 条回复    2020-07-31 10:36:05 +08:00
    bi531334444
        1
    bi531334444  
       2020-06-06 11:13:34 +08:00
    for of + async await ?
    ericls
        2
    ericls  
       2020-06-06 11:19:40 +08:00
    promise.all?
    cxe2v
        3
    cxe2v  
       2020-06-06 11:22:06 +08:00
    foreach 我记得是同步的
    VDimos
        4
    VDimos  
       2020-06-06 11:29:04 +08:00 via Android
    foreach 是异步是啥意思?
    mazai
        5
    mazai  
       2020-06-06 12:12:14 +08:00
    重新定义 foreach👍
    mikicomo
        6
    mikicomo  
       2020-06-06 12:24:44 +08:00
    写 java 的,不过题主的意思我明白了,foreach 中循环的方法体中调用了异步方法,而你又需要在后面的代码中使用 foreach 循环体中生成的数据,对标 java 中的 Future,可以搜一下 js 中怎么实现的
    ljpCN
        7
    ljpCN  
       2020-06-06 12:55:23 +08:00
    别用 foreach,用 map+Promise.all
    px920906
        8
    px920906  
       2020-06-06 14:09:49 +08:00
    php 吗? js 用 promise 的话可以这样:
    ```js
    let queue = Promise.resolve()
    arr.forEach(e => {
    queue = queue.then(() => someAsyncFunc(e))
    })
    ```

    当然 async/await 也可以
    ```js
    async (function() {
    arr.forEach(e => {
    await someAsyncFunc(e)
    })
    })()
    ```
    cnrting
        9
    cnrting  
       2020-06-06 14:11:12 +08:00 via iPhone
    for 循环不是同步的吗???
    Trim21
        10
    Trim21  
       2020-06-06 14:12:37 +08:00 via Android
    楼主的意思是 foreach 传进的那个函数是异步的…
    seki
        11
    seki  
       2020-06-06 14:15:05 +08:00
    用 bluebird.each 或者 p-each-series 这样的库
    meteor957
        12
    meteor957  
       2020-06-06 14:33:59 +08:00 via Android
    reduce
    will0404
        13
    will0404  
       2020-06-06 14:43:28 +08:00
    ```
    const arr = [1, 2, 3];
    const promises = [];
    arr.forEach(v => {
    promises.push(Promise.resolve(v));
    });
    Promise.all(promises).then(result => {
    console.log(result); // [1,2,3]
    });
    ```
    falcon05
        14
    falcon05  
       2020-06-06 14:45:43 +08:00 via iPhone
    foreach 是同步的好吗?
    WittBulter
        15
    WittBulter  
       2020-06-06 14:53:36 +08:00
    1. 继发: Loop await 即可
    2. 继发 Iterator: for await of 即可
    3. 并发: Promise.all([].map(async item => await todo(item))) 是比较简单的方式
    4. 并发但忽略 reject 直到所有异步都完成: 3 改成 Promise.allSettled 。其他的并发但状态需求不同可参考其他 Promise 静态方法

    8 楼的例子还有其他几楼由明显错误,await 只能在 async 下,即便 forEach 了 async,在可读性上也是误以为继发的并发任务,有阅读歧义。此外 forEach 是典型的副作用的函数。
    a132811
        16
    a132811  
       2020-06-06 16:02:37 +08:00
    多提了下。
    @WittBulter 最新的 v8 已经支持 top await 了,不用限制 await 在 async 了。

    目前 deno 、chrome 80 、firefox 72 已支持 top await.
    ````
    export default config = await Promise.resolve({env:'dev'})
    ```
    gauzung
        17
    gauzung  
       2020-06-06 20:59:02 +08:00
    async fun(){for(...){await ...}}
    每次循环请求一个接口,成功 /失败后才执行下一次循环
    JayLin1011
        18
    JayLin1011  
       2020-06-06 21:15:22 +08:00
    for..await...of 或者 Promsie.all(),异步并发问题一般需要计数器作为哨兵变量。
    wangyzj
        19
    wangyzj  
       2020-06-07 01:00:51 +08:00
    foreach 是同步的
    qinfensky
        20
    qinfensky  
       2020-06-07 08:13:58 +08:00 via iPhone
    @px920906 你这个是不是有问题的呢?在 foreach 的匿名函数中 await 应该是不可以的吧。作用域变动了,用 for 就可以 await
    px920906
        21
    px920906  
       2020-06-07 12:23:40 +08:00
    @WittBulter @qinfensky 是的,,写了个不负责任的回答,惭愧,谢谢指出。
    自己试了一下,即使 async 放在 forEach 的匿名函数前也没用,会并行执行,查了一下这好像是个常见的误区。
    http://objcer.com/2017/10/12/async-await-with-forEach/
    https://stackoverflow.com/questions/37576685/using-async-await-with-a-foreach-loop
    ruby109
        22
    ruby109  
       2020-06-09 12:10:52 +08:00
    const a = await Promise.all(array.map(async element => {
    return await asyncFunction();
    });
    source
        23
    source  
       2020-07-10 11:41:57 +08:00
    指出一点:forEach 的回调不能直接套 async/await
    其他的方式都没问题,比如 promise.all
    jake361
        24
    jake361  
       2020-07-31 10:36:05 +08:00
    foreach 就是同步得啊,你的意思是不是在 foreach 里面异步调用?
    有两种解决方案,一个是 Promise all,配合 async await,最新版本的 node 应该支持了
    如果是老版本的 node,有一个库 http://caolan.github.io/async/v3/, 应该可以解决你的问题
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1013 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 35ms · UTC 20:00 · PVG 04:00 · LAX 12:00 · JFK 15:00
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.