另一个映射调用中的 async Array.map()

You*_*mad 5 javascript async-await

我有一个接收配置文件数组的方法,我必须为每个配置文件进行映射,并且在该地图内我必须在照片属性中再次映射,其中包含用于请求 API 来获取此图片的图片 ID。

问题是,我在哪里可以安全地访问这个配置文件数组及其加载的每个配置文件的照片?

profiles.map((profile, i) => {
    let photos = []

    Promise.all(profile.photos.map(async idPhoto => { 
        const res = await fetch(...)
        const img = await res.blob()
        photos.push(img)
    }))

    .then(() => profiles[i].photos = [...photos])
})
Run Code Online (Sandbox Code Playgroud)

rh1*_*h16 2

map按照当前外部函数的方式,Promise.all()调用将被丢弃,因此您的代码无法检测它们何时完成。

但是,由于您似乎也没有使用外部映射的返回值,因此我们可以使其返回一个 Promises 数组,当内部 Promises 数组全部解析时,该数组会解析。然后我们可以使用Promise.all(array.map())与内部地图相同的模式。

const photoRequests = profiles.map(async (profile, i) => {
      let photos = []

      await Promise.all(profile.photos.map(async idPhoto => { 

        const res = await fetch(...)
        const img = await res.blob()
        photos.push(img)
      }));

      profiles[i].photos = [...photos];
})

// And now...

await Promise.all(photoRequests); 
// After this it is safe to access.

// Or, if the outer map is not in an async method:

Promise.all(photoRequests).then(() => {
  // It is safe to access profiles here
});
Run Code Online (Sandbox Code Playgroud)

我已将外部映射重构为异步函数(在我看来有助于提高可读性),但如果您愿意,可以将其放回去。只需让外部映射函数返回调用结果即可Promise.all

至于这里还有什么可以改进的地方,有变量photosprofile.photos有点令人困惑,所以考虑重命名photos。也请在您执行此操作时进行操作const,因为它永远不会被重新分配。

除非有其他代码可以操作photos数组,否则不需要数组扩展语法。索引变量也是如此。最终代码可能类似于:

const photoRequests = profiles.map(async profile => {
      const loadedPhotos = []

      await Promise.all(profile.photos.map(async idPhoto => { 

        const res = await fetch(...)
        const img = await res.blob()
        loadedPhotos.push(img)
      }));

      profile.photos = loadedPhotos;
})


await Promise.all(photoRequests); 
Run Code Online (Sandbox Code Playgroud)

或者您可以使用解析为一个数组的事实,该Promise.all数组包含它收到的各个承诺的解析值:

const photoRequests = profiles.map(async profile => {

      profile.photos = await Promise.all(
        profile.photos.map(async idPhoto => { 

          const res = await fetch(...)
          return res.blob()

        })
      );
})


await Promise.all(photoRequests); 
Run Code Online (Sandbox Code Playgroud)