一、forEach外部等待forEach执行完成
let arr = [1, 2, 3, 4, 5, 6, 7];
let arr2 = [];
arr.forEach((item) => {
setTimeout(() => {
arr2.push(item);
}, 1000);
});
console.log(arr2); // []
如上:当forEach内部处理异步操作时,则forEach同时也处于异步状态,并不会阻塞进程,而是让下面的语句先执行
即如果在使用forEach遍历数组时,forEach内有异步操作,那么后面的代码执行是不会等待forEach的执行结果,但是很明显我们想要拿到的是forEach结束后的数据,此时我们只需要将forEach写到promise里,即使forEach处于同步状态。
把每次的循环都包裹到一个Promise里,形成一个Promise队列(asyncFuns),最后使用Promise.all来判断是否全部执行完毕
let arr = [1, 2, 3, 4, 5, 6, 7];
let arr2= [];
function pro(item) {
return new Promise((resolve, reject) => {
setTimeout(() => {
arr2.push(item);
resolve();
}, 10000);
});
}
let asyncFuns = [];
arr.forEach((item) => {
asyncFuns.push(pro(item));
});
Promise.all(asyncFuns).then(() => {
console.log('res', arr2); // 十秒钟后打印:res (7) [1, 2, 3, 4, 5, 6, 7]
});
二、forEach内部等待异步执行完成
let arr = [1, 2, 3, 4, 5, 6, 7];
let arr2 = [];
function pro(item) {
return new Promise((resolve, reject) => {
setTimeout(() => {
arr2.push(item);
console.log(arr2);
resolve();
}, 1000);
});
}
arr.forEach(async (item) => {
await pro(item);
console.log('这里是等待每一次循环结束后的操作');
});
三、既需要forEach内部同步执行,又需要forEach外部同步执行
forEach方法用于调用数组的每个元素,并将元素传递给回调函数
map方法返回一个新数组,数组中的元素为原始数组元素调用函数处理后的值
由于forEach执行并不返回任何数据,则无法使用Promise.all方法进行循环是否结束的判断,于是我们想到了使用map+Promise.all来处理这种情况
// 使用map进行数组遍历处理
let arr = [1, 2, 3, 4, 5, 6, 7];
let arr2 = [];
function pro(item) {
return new Promise((resolve, reject) => {
setTimeout(() => {
arr2.push(item);
console.log(arr2);
resolve();
}, 1000);
});
}
Promise.all(
arr.map((item) => {
return new Promise(async (resolve, reject) => {
await pro(item);
console.log('这里是等待每一次循环结束后的操作');
resolve();
});
})
).then(() => {
console.log('res', arr2);
});
但是实际上forEach也可以手动设定条件来判断是否遍历结束,由于forEach遍历为顺序执行遍历,所以我们可以使用当前项的index值来判断当前项是否为该数组的最后一项,如果为最后一次遍历,那么我们让程序执行下一步的操作即可
// 使用forEach进行数组遍历处理
let arr = [1, 2, 3, 4, 5, 6, 7];
let arr2 = [];
function pro(item) {
return new Promise((resolve, reject) => {
setTimeout(() => {
arr2.push(item);
console.log(arr2);
resolve();
}, 1000);
});
}
arr.forEach(async (item, index) => {
await pro(item);
console.log('这里是等待每一次循环结束后的操作');
if (index === arr.length - 1) {
console.log('res', arr2);
}
});