今天遇到个问题,想让for循环结束了再resolve(arr)。
但后面这些代码好像只执行了一次,最开始以为是for循环只执行了一次,后面发现应该是forEach和await的锅,执行请求时已经是循环的最后一次,await没起作用。
async function uploadChunk() {
return new Promise(async (resolve, reject) => {
await handleFileChange();
console.log('formDataArr', formDataArr);
let arr = [];
let counter = 0;
for (let index = 0; index < formDataArr.length; index++) {
console.log('index', index);
const items = formDataArr[index];
formDataArr[index].forEach((item) => {
try {
// const res = await axios.get("/uploadFile");
const res = await uploadFile(item.get("file"), item.get("name"), item.get("chunks"), item.get("chunk"));
console.log('uploadFile-res', res);
if (item.get("chunks") - 1 == item.get("chunk")) {
arr.push(res.data); // 分片后最终结果
}
counter++;
if (counter === formDataArr.length) {
resolve(arr); // 当计数器等于数组长度时,所有操作都完成,调用 resolve
})
} catch (error) {
reject(error);
return;
}
}
}
})
}
循环可能只执行了一次的原因是异步操作的执行顺序导致的。
在这段代码中,formDataArr[index].forEach 中的回调函数是异步的。当你遍历 formDataArr 中的第一个元素时,在执行 formDataArr[index].forEach 时,内部的异步操作 axios.get("/uploadFile") 开始执行,但是并没有等待异步操作完成,而是继续执行循环的下一个迭代。
因为循环的第二次迭代是在异步操作还没完成的情况下开始的,第一个异步操作可能还没有机会执行完成。所以,整个循环可能会很快的完成并退出,而不是等待异步操作的结果。
为了确保循环正确执行和等待所有异步操作完成,可以将 forEach 循环改为 for...of 循环,以便可以使用 await 关键字等待每个异步操作完成。修改后的代码如下:
for (let index = 0; index < formDataArr.length; index++) {
console.log('index', index);
const items = formDataArr[index];
for (const item of items) {
try {
const res = await axios.get("/uploadFile");
console.log('uploadFile-res', res);
if (item.get("chunks") - 1 == item.get("chunk")) {
arr.push(res.data); // 分片后最终结果
}
counter++;
console.log('counter', counter);
console.log('formDataArr.length', formDataArr.length);
if (counter === formDataArr.length) {
resolve(arr); // 当计数器等于数组长度时,所有操作都完成,调用 resolve
}
} catch (error) {
reject(error);
return;
}
}
}
通过使用 for...of 循环,可以确保在每次迭代中都等待异步操作的完成,以及避免了可能导致循环直接退出的问题。这样,你就可以正确执行多次循环,并等待所有异步操作完成后再调用 resolve。
总结:forEach不能支持异步调用,解决这个方法就是将forEach方法换成普通for循环/for of就可以了