Node中数组的forEach方法探讨

作者:凡江林 QQ:564438737

1.问题描述

在Node中,经常存在异步执行的情况。如下代码片段所示:

let k=1;
let sum=0;
let array=[2,4,6,8,10];
array.forEach(x=>{
    //模拟forEach中存在异步操作的情况。
    setTimeout(()=>{
        sum+=x;
    },2000)
    
})
console.log("sum="+sum);

我们的期望结果是:sum=30。但在Node中运行,你会看到如下图所示的结果:

那问题出在哪里呢,为什么会产生与预期不一致的结果?

2.问题分析及应对策略

经过分析,出现以上结果的原因是:当forEach中存在异步操作的时候,流程会跳过forEach,直接执行后面的console.log。从而,在sum还未赋值之前,就输出了sum的结果。

那如何解决这个问题呢?当然,解决问题的方式有很多种,在此,想到了把console.log代码移动到forEach内部,如下所示:

let k=1;
let sum=0;
let array=[2,4,6,8,10];
array.forEach(x=>{
    //模拟forEach中存在异步操作的情况。
    setTimeout(()=>{
        sum+=x;
        console.log("sum="+sum);
    },2000)
    
})

直觉告诉你,每一次forEach循环,都会执行一次console.log。如下图所示:

但我们并不需要前面4次的sum输出。如何解决呢?我们需要设置一个条件,当forEach执行最后一次加法的时候,我们就执行输出,代码如下所示:

let k=1;
let sum=0;
let array=[2,4,6,8,10];
let len=array.length;
array.forEach(x=>{
    //模拟forEach中存在异步操作的情况。
    setTimeout(()=>{
        sum+=x;
        if(k==len){
            console.log("sum="+sum);
        }
        k=k+1;
        
    },2000)
    
})

执行结果如下图所示:

3.推广应用

在Node中,模块是普遍存在的一种情况。假设我们需要在模块中利用forEach执行一个集合,然后返回对集合元素操作的最终结果。可以如下所示来避免异步操作带来的不一致问题。

function addForeach(array, callback) {
    let k = 1;
    let sum = 0;
    //let array=[2,4,6,8,10];
    let len = array.length;
    array.forEach(x => {
        //模拟forEach中存在异步操作的情况。
        setTimeout(() => {
            sum += x;
            if (k == len) {
                console.log("sum=" + sum);
                return callback(sum);
            }
            k = k + 1;

        }, 2000)

    })
}

module.exports={
    addForeach
}

但如果按照同步的思维方式,把sum的回调放在forEach外部下方,经过测试,得不到所期望的结果,有兴趣的读者可以测试一下,在此不在详述。仅把遇到的问题及解决策略分享出来,供遇到相似问题的读者参考。
(限于作者的学识和经验,定有不少疏漏和不当之处,甚至是错误也在所难免,恳请读者和同行批准指正!)

猜你喜欢

转载自blog.csdn.net/fanjianglin/article/details/94056097