等待所有文件更新,然后下载它们

Wait for all files to update, then download them

我正在使用库 JSZip 创建 .png 文件并将它们添加到 zip 存档以供下载。当我添加太多大文件时,问题就来了。

我使用一组 for 循环将文件添加到 zip,然后激活自动下载。问题似乎是下载在文件更新之前开始,因此它们最终没有数据。

for (var row = 0; row < 3; row++) { // Loop for rows
  for (var col = 0; col < 3; col++) { // Loop for cols
    if (cropSrc[row][col]) { // If data for cropped img exists
      var fileName = row + "" + col + ".png";
      zip.file(fileName, cropSrc[row][col].src, {
        base64: true
      }); // Add file to zip

      zip.file(fileName).async("uint8array").then(function(u8) { // Once file is complete... I think
        console.log("done");
      });

    }
  }
}

// Download zip file
zip.generateAsync({
  type: "base64"
}).then(function(base64) {
  window.location = "data:application/zip;base64," + base64;
});

我必须确保在下载之前等到所有文件都已更新,如何使用异步函数执行此操作?

这里是JSZip Async Documentation


不确定这是否有帮助,但这里是对完整代码的更完整的了解,我正在使用 SAPUI5 并在 SAP Web 中开发 IDE:

var cropSrc = {
    0: {
        0:{src:"base64 data placeholder"},
        1:{src:"base64 data placeholder"},
        2:{src:"base64 data placeholder"}
    },
    1: {
        0:{src:"base64 data placeholder"},
        1:{src:"base64 data placeholder"},
        2:{src:"base64 data placeholder"}
    },
    2: {
        0:{src:"base64 data placeholder"},
        1:{src:"base64 data placeholder"},
        2:{src:"base64 data placeholder"}
    }
};

sap.ui.define([
    "sap/ui/core/mvc/Controller",
    "SAP_SARAH_ML_Project/libs/jszip", // Enables the jszip library (imports)
], function(Controller, jszipjs) { // Second part of importing
    "use strict";
    return Controller.extend("SAP_SARAH_ML_Project.controller.View1", {

        zipImg: function() {
            for (var row = 0; row < 3; row++) { // Loop for rows
                for (var col = 0; col < 3; col++) { // Loop for cols
                    if (cropSrc[row][col]) { // If data for cropped img exists
                        var fileName = row + "" + col + ".png";
                        zip.file(fileName, cropSrc[row][col].src, {
                            base64: true
                        }); // Add file to zip

                        zip.file(fileName).async("uint8array").then(function(u8) { // Once file is complete... I think
                            console.log("done");
                        });

                    }
                }
            }

            // Download zip file
            zip.generateAsync({
                type: "base64"
            }).then(function(base64) {
                window.location = "data:application/zip;base64," + base64;
            });
        }
    });
});

您可以为此使用 Promise.all:

let arr = [addFilePromise('file1'),addFilePromise('file2'),addFilePromise('file3')]
Promise.all(arr).then(zip.generateAsync({type:"base64"}))

编辑:

let fileAddActions = [];

let addFilePromise = function(filename){
    zip.file(fileName, cropSrc[row][col].src, {
        base64: true
    }); 

    return zip.file(fileName).async("uint8array")
}


for (var row = 0; row < 3; row++) { // Loop for rows
    for (var col = 0; col < 3; col++) { // Loop for cols
        if (cropSrc[row][col]) { // If data for cropped img exists
        var fileName = row + "" + col + ".png";
        fileAddActions.push(addFilePromise(fileName))

        }
    }
}


Promise.all(fileAddActions).then(zip.generateAsync({type:"base64"})).then(base64 => {
    indow.location = "data:application/zip;base64," + base64;
})

像这样的东西应该有用,我也推荐这篇文章: https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/Promise

因为 async returns 是一个 Promise,所以您可以将执行 for 循环的函数设为 async/await 函数

async functionName() {
   for loop...
      let res = await zip.file(fileName).async("uint8array");
}

参考这个

它使用一种称为 parallelimit 的东西作为信号量来异步处理有限数量的文件,然后将其压缩。