等待不等待异步功能

时间:2020-11-01 19:41:21

标签: javascript async-await

我正在学习异步/等待,但是我真的不知道这里出了什么问题。为什么我在使用myArray时总是空着?我该如何解决?

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?

2 个答案:

答案 0 :(得分:2)

传递给forEach的回调不是同步的,它可以工作,但不能达到预期。迭代完成后,异步函数“ preparePhotos”将立即返回。

我认为您应该改用for循环。

PD:我不知道这个问题是否重复了Using async/await with a forEach loop

答案 1 :(得分:1)

在forEach循环中使用await时,是在告诉js引擎在lambda而不是整个函数中“等待”。

如果您希望能够等待preparePhotos函数,则需要一些如何从lambda中“等待”。

首先定义一个诺言

let promises = [];

然后,不要等待getFileAsBinary返回的诺言,而是将其追加到列表中

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

您现在有了一个诺言列表,可以使用Promise.all等待列表中的所有诺言

let myArray = await Promise.all(promises);

Promise#all返回由原始数组中的promise解析的所有值的列表,因此它将有效地返回原始的“ myArray”。

或者,使用for循环(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);
}