nodejs中forEach和普通循环区别

问题描述:
最近在写代码中发现在forEach循环中,使用await函数跟正常的循环有区别,所以进行记录。
一般我们都将forEach叫做增强for循环,确实减少了部分代码量,但是当内部使用await的时候需要注意,下面我写了两个例子。

1、如果在循环中不使用await这个promise,区别不大
2、forEach和普通循环中执行await函数情况
(1)forEach
[1,2,3].forEach(function hehe),先执行hehe(1),假如hehe里面有异步,就不会等它执行完,继续执行hehe(2)了,所以有可能出现,整个函数执行完了,但是forEach里面的函数还没执行完

async function test(){
    console.log('start');
    const arr = [1,2,3]
        arr.forEach(async(t)=>{
            await new Promise((resolve)=>{setTimeout(()=>{resolve()},1000)})
            console.log(t);
        })
    console.log('end');
}
test();

打印出来的结果是:start end 1 2 3
(2)普通循环

async function test() {
  console.log('start');
  const arr = [1, 2, 3]
  for (let index = 0; index < arr.length; index++) {
    const element = arr[index];
    await new Promise((resolve) => { setTimeout(() => { resolve() }, 1000) })
    console.log(arr[index]);
  }
  console.log('end');
}
test();

打印结果为: start 1 2 3 end ,这才是我们需要的结果
for(let t of arr){await func(t)},这样子是一个promise完才进行下一个,很多时候我们是需要这样的

想:如果我们需要写jest测试的时候,对于两种情况,写的测试代码也应该是稍有区别的,普通循环的话我们只需要在测试的时候用await来写,但是forEach因为在真正打印出来值之前已经结束了promise,那么写的时候是需要setTimeout设置几秒的。

3、forEach和普通循环中执行同步函数
代码我就不粘贴了,只需要把上面两处的代码中await new Promise((resolve) => { setTimeout(() => { resolve() }, 1000) })注释掉即可,测试发现,两个循环最终结果都是:start 1 2 3 end

4、理论知识的区别:
(1)for循环是可以使用break和continue去终止循环的,但是forEach不行
(2)forEach代码量少
(3)for多数时候都可以使用,当然一般需要知道循环次数,而forEach更适合集合对象的遍历和操作
(4)注意内部使用await的情况
(5)只能对元素进行顺序的访问,只能访问数组或集合中的所有元素,循环中没有当前索引

注意:
forEach(function),这个function里面抛出的error或者reject的promise是不会被外层的try catch捕获的.

async function test(){
    const arr = [1,2,3]
    try{
        arr.forEach((t)=>{
            return Promise.reject(`error${t}`);
        })
    } catch(err){
        console.log(err);
    }
}
test();

forEach本身是同步的,假如里面的函数式同步的,抛出的error是会被外面的try捕捉到的,假如是异步的,抛出的error就捕捉不到
运行之后会出现未捕获的reject promise
如果把return Promise.reject(error${t})换成抛出error的话就会直接崩掉
因为这个function已经算是另一个上下文了

reject的promise是不会宕机的,回调里抛出的error外面捕获不到会宕机

你可能感兴趣的:(nodejs)