【问题标题】:How to keep code synchronous when there are asynchronous calls inside of loops当循环内有异步调用时如何保持代码同步
【发布时间】:2019-07-02 05:01:00
【问题描述】:

我正在循环中填充一个数组,循环结束时我需要完整的数组。

我尝试过通过承诺或使用计数器来处理所有事情,但我似乎无法弄清楚这里的诀窍。

lambda.listFunctions({}).promise()
    .then((data) => {
        data.Functions.forEach(func => {
            lambda.listTags({ Resource: func.FunctionArn }).promise()
                .then((data) => {
                    if ("Edge" in data.Tags) {
                        available_functions.push(func.FunctionName)
                    }
                })
        });
          console.log(available_functions)
    })

available_functions 始终为空,除非我在每个 foreach 循环结束时通过控制台记录它,然后让它返回 18 次,这不是我想要的。

【问题讨论】:

  • 你能用await关键字吗?
  • 我已经尝试通过在 foreach 中异步使用匿名函数并使用 await 但它并没有减慢这个坏男孩的速度,或者至少我没有正确使用它
  • “循环结束时我需要完整的数组”实际上是做不到的。您可以构造一个promises 数组来提供数据,并在所有数据到达时使用Promise all 继续进行,或者删除forEach 循环并编写一个异步循环和await 单独的数据promises。在任何一种情况下,都无法处理与发出请求同步获得的数据。

标签: javascript node.js amazon-web-services asynchronous


【解决方案1】:

您可以使用Promise.all 解决您的问题。请参阅Promise.all() 上的文档。

const available_functions = [];

lambda.listFunctions({}).promise()
    .then((data) => {
        const promises = []; // Collect promises

        data.Functions.forEach(func => {
            promises.push(lambda.listTags({ Resource: func.FunctionArn }).promise()
                .then((data) => {
                    available_functions.push(func.FunctionName)
                    return Promise.resolve(available_functions);
                })
            );
        });

        Promise.all(promises)
            .then(results => {
                    console.log(available_functions)
                // or
                    console.log(results[results.length - 1]);
            });
    });

【讨论】:

    【解决方案2】:

    我相信你可以承诺它链接它,以确保 then 范围内的所有操作在下链之前完成。

    lambda.listFunctions({}).promise()
      .then(data => {
        const { Functions } = data;
    
        // I converted this from forEach to for of
        for (const func of Functions) {
          lambda.listTags({ Resource: func.FunctionArn }).promise()
            .then(data => {
              if ("Edge" in data.Tags) {
                available_functions.push(func.FunctionName)
              }
            })
        }
      // also you can promise chain it if available_functions is within scope
      })
      .then(() => console.log(available_functions))
    

    或者更清洁的async await 方式看起来像......

    async fn() {
      const available_functions = [];
    
      const { Functions } = await lambda.listFunctions({}).promise();
    
      for (const func of Functions) {
        const tags = await lambda.listTags({ Resource: func.FunctionArn }).promise();
    
        if ("Edge" in tags) {
          available_functions.push(func.FunctionName)
        }
    
      }
    
      return available_functions
    
    }
    

    希望这会有所帮助!

    【讨论】:

    • 您可能误读了链接文章 - for.. of 循环是同步的。
    • @traktor53 好电话。是的,绝对是误读。我更新了我的评论,希望代码仍然有效
    猜你喜欢
    • 2020-06-27
    • 2015-04-18
    • 1970-01-01
    • 2018-10-17
    • 1970-01-01
    • 1970-01-01
    • 2018-03-12
    • 2021-12-12
    • 2018-03-09
    相关资源
    最近更新 更多