使用 foreach 循环创建数组并使用 webworker postMessage 传回

Create array using foreach loop and pass it back with webworker postMessage

我有这个网络工作者代码:

onmessage = (e) => {
  console.log(e);
  fetch('https://example.com/wp-json/wp/v2/posts?per_page=20')
  .then( (res) => res.json() )
  .then( async (data) => {
    let imagesData = [];
    data.forEach( (item) => {
      fetch(item._links["wp:featuredmedia"][0].href)
      .then( (res) => res.json() )
      .then( (img) => {
        imagesData.push({
          title: item.title.rendered,
          link: item.link,
          src: img.source_url
        });
      });
    });
    await postMessage([imagesData]);
  });
} //end onmessage

我正在尝试在获取所有资源后创建一个数组,但我无法实现。目前 imagesData 数组将为空,如果将其移动到推送数组数据的 .then() 中,我将收到多条消息,每个数组包含一个条目。我如何解决这个问题,让一个数组包含所有获取的信息以传回创建工作程序的位置?

注意:该代码在我的主脚本中运行良好,我只是将其移交给网络工作者!问题不在于 fetch 提供的数据及其结构,而在于 imagesData 数组,这是我想要填充并发送回主脚本的数组。

Array#forEach 同步执行,所以当你到达 postMessage 时,数组仍然是空的。

相反,您需要的是 Promise.all

Promise.all 将一组 promise 转换为单个 promise,该 promise 解析为一组已解析的值。内部承诺是并行执行的,因此解决时间应该大致与 longest-running 内部承诺的时间一样长。

方便地,将 async 函数作为回调传递给 Array#map 将原始数组转换为承诺数组。一种常见的用法是使用 fetch 请求映射 URL 字符串或参数数组,将结果包装在 Promise.all:

const usernames = await Promise.all(
    ['123', '456', '789'].map(async id => {
        const res = await fetch(`/api/users/${id}`)
        const { username } = await res.json()

        return username
    })
)

在你的情况下,你需要替换这个:

let imagesData = [];
data.forEach( (item) => {
  fetch(item._links["wp:featuredmedia"][0].href)
    .then( (res) => res.json() )
    .then( (img) => {
      imagesData.push({
        title: item.title.rendered,
        link: item.link,
        src: img.source_url
      });
    });
  });
await postMessage([imagesData]);

有了这个:

const imagesData = await Promise.all(
    data.map(async item => {
        const res = await fetch(item._links["wp:featuredmedia"][0].href)
        const img = await res.json()
        return {
            title: item.title.rendered,
            link: item.link,
            src: img.source_url
        }
    })
)

另外,worker的postMessage是同步的,没必要await。您也不需要在发布之前将 imagesData 包装在外部数组中:

postMessage(imagesData);