jszip icon indicating copy to clipboard operation
jszip copied to clipboard

how to get data from .async("string") in a loop?

Open PaddleStroke opened this issue 3 years ago • 2 comments

I'm using JSZip to access files inside a zip. In that .zip there is one file that I'm looking for and I need it's content. To get the content it seems to require an async function. Which is called multiple times in a for loop.

My problem is that when I find the correct file, I'm in an async function so trying to get the value from the main program tell me 'undefined'. But I can't continue my code inside that async function because it's called in a loop so I would end running my main program many times.

var fileToFind;

JSZip.forEach(function (relativePath, file){
    
    var fileAsStr = JSZip.file(relativePath).async("string"); //this is the way to get file content in JSZip
    
    const waitStr = async () => {
        fileAsStr = await fileAsStr;
        const anchorStr = "Some string which is in only one file";
        if(fileAsStr.indexOf(anchorStr) != -1){
            fileToFind = fileAsStr;
            console.log(fileToFind); //works ok
        }
    waitStr();
});

... //lot of stuff

console.log(fileToFind); //undefined

PaddleStroke avatar Sep 01 '21 13:09 PaddleStroke

You have to wait somewhere on your asyncs. First thing coming to mind is to collect the files from JSZip in a first step and then do a iterate over it. Maybe something like (there may be better ways!):

const allFiles = []

JSZip.forEach(function (relativePath, file){allFiles.push(relativePath)})

And then:

async function find() {
  for(const relativePath of allFiles) {
      const fileStr = await JSZip.file(relativePath).async("string")

      if(...match...) return { relativePath, fileStr }
  }
}

Most important you have to WAIT for the result before using it, e.g.

console.log(await find())

// OR - but then you have to make sure that the program does not stop before the ZIP has scanned.
find.then(function(result){ console.log(result) }, function(err){console.error("ups" + err.message)})

In general: using async/await seems to make things easy but only if you look a bit deeper. If you have something async must must wait for the operation to finish. Best way to understand is that

  const y = await x()
  console.log(y)

is (nearly) equivalent to

x().then(function(y){console.log(y)})

OR: x() only spawns a background activity running somewhen in the future (concept of Promise).

JMS-1 avatar Sep 02 '21 06:09 JMS-1

Thanks for your explanations !

PaddleStroke avatar Sep 02 '21 19:09 PaddleStroke