有没有一种好的方法可以Promise.all一个具有promise属性的对象数组?

6
如果我有一个 promise 数组,我可以使用 Promise.all 等待它们全部完成。
但是如果我有一个对象数组,每个对象都有一些属性是 promises,有没有好的方法来处理它呢?
示例:
const files=urlOfFiles.map(url=>({
  data: fetch(url).then(r=>r.blob()),
  name: url.split('/').pop()
}))
//what to do here to convert each file.data to blob?
//like Promise.all(files,'data') or something else
3个回答

10

与其将数据映射到对象数组,不如将其映射到一组解析为对象的 promises 数组:

const promises = urlOfFiles
    .map(url => fetch(url)
        // r.blob() returns a promise, so resolve that first.
        .then(r => r.blob())
        // Wrap object in parentheses to tell the parser that it is an
        // object literal rather than a function body.
        .then(blob => ({
            data: blob,
            name: url.split('/').pop()
        })))

Promise.all(promises).then(files => /* Use fetched files */)

但是如果一个文件对象有多个属性是promise,我需要编写嵌套回调吗? - 3142 maple
这肯定会让它更加复杂。一个 Promise.all() 数组可能会起作用(类似于这个答案,但使用 Promise.all(...) 而不是 fetch(url))。 - Tulir

1
尝试像这样做:

尝试像这样做:

const files = urlOfFiles.map(url=>
  fetch(url).then(r=> ({
    data: r.blob()
    name: url.split('/').pop()
  })
  ))
Promise.all(files)

与另一个答案的评论相同:结果对象数组将不会具有 blob 数据,而是 promise。 - dfsq

1

如果返回值有多个异步属性,你可以使用嵌套的Promise.all(如果其他异步结果依赖于fetch的响应),或者像Tulir建议的那样; 从Promise.all([fetch(url),other])...开始:

Promise.all(
  urlOfFiles.map(
    url=>
      fetch(url)
      .then(
        r=>
          Promise.all([//return multiple async and sync results
            r.blob(),
            Promise.resolve("Other async"),
            url.split('/').pop()
          ])
      )
      .then(
        ([data,other,name])=>({//return the object
          data,
          other,
          name
        })
      )
  )
)
.then(
  files=>
    console.log("files:",files)
);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接