Home > Software design >  JS wait until load event in filereader is done
JS wait until load event in filereader is done

Time:08-22

I have a JavaScript program, (it's actually a TypeScript program), that reads a file chunk by chunk with a FileReader:

while (j < size) {
    let blob = selectedFiles[i].slice(offset, offset   chunk_size);
    let reader = new FileReader();
    reader.addEventListener('load', async function () {
        let wordArray = typeof reader.result === "string" ? CryptoES.lib.WordArray.create(new TextEncoder().encode(reader.result)) : CryptoES.lib.WordArray.create(reader.result);
        let segment = CryptoES.AES.encrypt(wordArray, pass).toString();
        segments.push(segment);
    });
    await reader.readAsArrayBuffer(blob);
    offset  = chunk_size;
    j  = chunk_size;
}

But when I process the segments Array later, it's empty. If I add an alert() after the while loop, wait a little bit after it appears and then press 'OK', my array has all it's contents it's supposed to have. My async/await doesn't seem to work properly. I'm using it inside an async function. What did I wrong?

Thank you!

EDIT: If you have other improvements for this piece of code, let me know in the comments as I'm still not a pro :)

CodePudding user response:

readAsArrayBuffer does not return a promise (it returns nothing, in fact), so it doesn't make sense to await it (that does nothing).

Instead, you need to create a promise that resolves when the load event fires and wait on that. I put this part into a separate function readBlobToArrayBuffer for readability, and I also added event listeners on error and abort to reject the promise in that case instead of just hanging indefinitely.

const readBlobToArrayBuffer = blob => new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.addEventListener('load', () => resolve(reader.result));
    reader.addEventListener('error', () => reject(new Error('Reading file failed'));
    reader.addEventListener('abort', () => reject(new Error('Reading file aborted'));
    reader.readAsArrayBuffer(blob);
});

while (j < size) {
    const blob = selectedFiles[i].slice(offset, offset   chunk_size);
    const result = await readBlobToArrayBuffer(blob);
    const wordArray = typeof result === "string"
      ? CryptoES.lib.WordArray.create(new TextEncoder().encode(result))
      : CryptoES.lib.WordArray.create(result);
    const segment = CryptoES.AES.encrypt(wordArray, pass).toString();
    segments.push(segment);
    offset  = chunk_size;
    j  = chunk_size;
}
  • Related