Wait for all files to update, then download them

空扰寡人 提交于 2020-01-06 08:38:26

问题


I'm using the library JSZip to create .png files and add them to a zip archive to be downloaded. The problem comes when I add too many large files.

I use a set of for loops to add the files to the zip then activate an automatic download. The issue seems to be that the download starts before the files have been updated so they end up with no data.

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;
});

I have to make sure I wait till all files have been updated before downloading, how would I do this using async functions?

Here is JSZip Async Documentation


Not sure if this will help but here is a more complete look at the full code, I'm using SAPUI5 and developing in 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;
            });
        }
    });
});

回答1:


You can use Promise.all for this:

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

EDIT:

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;
})

something like this should work, also i recommend this article: https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/Promise




回答2:


Since async returns a Promise, you can make the function where you are doing the for loop an async/await function

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


来源:https://stackoverflow.com/questions/51638789/wait-for-all-files-to-update-then-download-them

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!