【问题标题】:How to wait for asynchronous JSZip .forEach() call to finish before running next code?如何在运行下一个代码之前等待异步 JSZip .forEach() 调用完成?
【发布时间】:2019-01-20 08:18:21
【问题描述】:

我有一个名为“data”的全局变量,它正在 forEach 循环中进行修改。但是,由于循环是异步的,因此代码不会等到填充数据后才继续执行代码。这是使用 JSZip 库。

let data = [];

await zip.folder("folderName").forEach(async function (relativePath, file) {
            let json = await zip.file(file.name).async("text");
            data.push(json);
            console.log(data.length); // prints increasing numbers
        });

console.log(data.length); //prints 0
// need to do something with data but it is empty

在继续代码之前如何等待填充数据数组?

【问题讨论】:

  • 查看 api,forEach 看起来不是异步的,所以向它发送一个承诺是行不通的,它期待一个回调..
  • @JJJ 不是真的。大多数答案和“很多很多其他人”会建议使用map(),这不是这里的选项,或者使用for 循环手动迭代集合,如果不对内部结构做出假设,这也是不可能的API。
  • 我看不到这里怎么不能使用地图。
  • @JJJ 可能想先查看 API,然后再将其作为重复项关闭。返回值不是一个数组,它是一个特定于 API 的对象。

标签: javascript typescript jszip


【解决方案1】:

forEach() 没有返回值,因此无法等待。您必须使用 Promise.all() 从每个 ZipObject#async()await 数组中填充一组 promise 以获得结果:

const promises = [];

zip.folder("folderName").forEach(function (relativePath, file) {
  promises.push(zip.file(file.name).async("text"));
});

Promise.all(promises).then(function (data) {
  // do something with data
});

【讨论】:

    【解决方案2】:

    根据 JSZip 文档,无法将 forEach(callback) 转换为 Promises 的数组。所以我想出的唯一方法是获取文件数量并使用计数器。

    const myFolder = zip.folder("folderName");
    const numberOfCallbacks = Object.keys(myFolder.files).length - 1;
    let counter = 0;
    myFolder.forEach((relativePath, file) => {
        // your code. you'd better create a Promise here and add it to an array of promises.
        counter++;
        if (counter === numberOfCallbacks) {
            // everything is done. If you created Promise above, here you can use Promise.all()
        }
    });
    

    我测试了上面的代码,它工作正常。如果有问题请告诉我。

    【讨论】:

      猜你喜欢
      • 2020-12-02
      • 1970-01-01
      • 2021-11-28
      • 2018-11-28
      • 1970-01-01
      • 1970-01-01
      • 2022-12-10
      • 2021-11-13
      相关资源
      最近更新 更多