forEach同/异步问题

一、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);
  }
});

在这里插入图片描述

  • 15
    点赞
  • 51
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值