0

I'm learning async/await but I really don't know what is wrong here. Why is my myArray always an empty when I use await? How can I solve this?

function getFileAsBinary(file) {
    return new Promise((resolve, reject) => {
        const reader = new FileReader();
        reader.readAsBinaryString(file);
        reader.onload = () => resolve(reader.result);
        reader.onerror = (error) => reject(error);
    });
};

const preparePhotos = async (photoFiles, myArray) => {

    photoFiles.forEach(async (photoFile) => {
        const photoBinary = await getFileAsBinary(photoFile);
        
        myArray.push("something")
    });
}
// ----------------------------------------------------
const myArray= [];
const photos = [file1,file2];

await preparePhotos(photos,myArray);
console.log(myArray); // getting [] here, why is it empty?
Samy
  • 1,013
  • 3
  • 15
  • 25

2 Answers2

2

The callbacks passed to the forEach are not synchronous, it can work, but not as expected. When the iteration is done the async function "preparePhotos" will return immediately.

I think you should use a for loop instead.

PD: not sure if this question is a duplicated of: Using async/await with a forEach loop

miguelps
  • 142
  • 3
  • 9
1

When you use await inside the forEach loop, you are telling the js engine to "wait" inside the lambda, not the overall function.

If you want to be able to await the preparePhotos function, you will need to some how get "await" out of the lambda.

Start by defining an array of promises

let promises = [];

Then instead of awaiting the promise returned by getFileAsBinary, append it to the list

photoFiles.forEach((photoFile) => {
    promises.push(getFileAsBinary(photoFile));
})

You now have a list of promises, and can use Promise.all to await all promises in the list

let myArray = await Promise.all(promises);

Promise#all returns a list of all values resolved by the promises within the original array, so it will return effectively your original "myArray".

Alternatively, use a for of loop (MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of)

for(let elem of photoFiles) {
    let binary = await getFileAsBinary(elem);

    myArray.push(binary);
}
Cameron R
  • 86
  • 4