【问题标题】:Using async/await in a loop在循环中使用 async/await
【发布时间】:2021-09-12 05:03:38
【问题描述】:

我知道已经有很多类似的问题,但似乎没有一个可以解决这个特定的问题。我有一个包含 forEach 循环的 Javascript 函数,在 forEach 循环内,有异步调用。

代码大致如下:

const handleConvert = () => {

    const refs = { ...imageRefs.current }

    // Outer loop
    Object.keys(refs).forEach(key => {
      
      // Inner loop
      refs[key].forEach(ref => {
        toPng(ref)
          .then((dataUrl) => {
            props.setImageUrls(old => {
              return {
                ..old,
                [key]: [...old[key], dataUrl]
              }
            })
          })
          .catch(err => {
            console.error(err)
          })
      })
    })
    setConverting(false)
    setConverted(true)
  }

refs 是一个包含 2 个键的对象,每个键都有一个数组作为其值。它看起来像这样:

{
  a: [1, 2, 3],
  b: [3, 4, 5]
}

toPng() 函数返回一个承诺。在外部 forEach 循环之后执行代码之前,我试图等待所有这些承诺得到解决:

if (mounted) {
  setConverting(false)
  setConverted(true)
}

有没有办法在执行外循环之后的代码之前等待所有的承诺解决?也许用 Promise.all()?

【问题讨论】:

    标签: javascript asynchronous es6-promise


    【解决方案1】:

    嵌套另一个 Promise.all 以等待每个子数组完成。确保将每个 Promise 映射并返回给调用者,以便 Promise.all 正常运行。

    Promise.all(
        Object.entries(refs)
            .map(([key, arr]) => Promise.all(
                arr.map(num =>
                    toPng(num).then(dataUrl => {
                        props.setImageUrls(old => ({ ...old, [key]: [...old[key], dataUrl] }))
                    })
                )
            ))
    )
        .then( // all done
    

    【讨论】:

    • 那是我的错误。在发布问题之前,我稍微更改了代码以使其更简单,但保持原样实际上很重要。我更新了原始问题。顺序确实很重要。生成的结构是一个对象,而不是一个数组。它与refs 对象的格式相同:2 个以数组为值的键。
    • 太棒了!这正是我想要做的。感谢您的帮助。
    猜你喜欢
    • 2019-07-16
    • 2016-12-30
    • 2018-01-12
    • 1970-01-01
    • 2020-08-03
    • 2020-05-30
    • 1970-01-01
    • 2017-04-29
    • 2021-10-15
    相关资源
    最近更新 更多