如何使用 JSZip 同步生成 zip 文件?

How to generate a zip file synchronously using JSZip?

我正在开发一个 React.js 应用程序,我有一个从 j=1j=2000 的循环我想在 j=1 或 j=2000 时下载一个 zip 文件。

问题是循环结束后同时下载了两个zip文件。换句话说,两个 zip 的下载在 j = 2000 时开始。

我尝试使用 async 和 await 同步生成 zip,但它对我不起作用。

const generateCollection = async ()=>{
    for(var j = 1; j <= 2000; j++){
      let zip = new JSZip();
      let metadata = zip.folder("metadata");
      const obj = {name: "Simple name", age: "Simple age"}
      metadata.file(`1.json`, JSON.stringify(obj, null, 4))

      console.log("Start Downloading: ", j)
      if(j===1 || j===2000){
        await zip.generateAsync({type:"blob"})
        .then(content=>{
          setIsLoading(false)
          FileSaver.saveAs(content, `collection_${j}.zip`);
          console.log("Saved...... ", j)
        })
      }
    }
 }

I will appreciate any help, or suggestion!!

这里的问题不在于 generateAsync 方法,而在于 saveAs,它被延迟到 cpu 可用并且无法等待,如此处所报告的:

https://github.com/eligrey/FileSaver.js/issues/389

一个解决方案可能是根本不等待,而是将循环转换为异步事件,让浏览器有时间在迭代之间显示保存对话框:

const generateCollection = ()=> {
    var j = 1;
    const loop = function() {
        if (j <= 2000) {
            let j2 = j; //Create a local copy of the loop var
            let zip = new JSZip();
            let metadata = zip.folder("metadata");
            const obj = {name: "Simple name", age: "Simple age"};
            metadata.file(`1.json`, JSON.stringify(obj, null, 4));
            
            console.log("Start Downloading: ", j)
            if (j2===1 || j2===2000){
                zip.generateAsync({type:"blob"})
                .then(content=>{
                    saveAs(content, `collection_${j2}.zip`);
                    console.log("Saved...... ", j2)
                });
            }
            j++;
            setTimeout(loop, 0);
        }
    };
    setTimeout(loop, 0);
}

$(function() {
        generateCollection();
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.7.1/jszip.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/2.0.0/FileSaver.min.js"></script>

请注意,由于安全限制,上述代码在 fiddle 中不起作用,您必须将其放在其他地方。