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