JavaScript forEach 循环:同步任务与执行顺序?

新手上路,请多包涵

目前生产出现了,handleDealData()返回的结果是[],并非是forEach执行后的数组,此问题偶发。
但是查了资料,解释说forEach的循环是同步任务。

            handleDealData: function () {
                var self = this
                var initData = self.deepCopyInitData;
                console.log("🐅  initData--->", initData)
                var val = []
                initData.forEach(function (obj, key) {
                    var _newObj_ = {
                        impartTarget: self.impartTarget,
                        insuredMark: self.insuredMark,
                        impartCode: obj.questList.notificationCode,  
                        showContent: obj.question,     
                        impartAnser: '',                  
                        showAnser: obj.active ? self.identity + ':' + obj.remark : '',
                        demo: obj.active ? obj.result : ''
                    }
                    var TAndF = Number(obj.active)
                    var allResult = obj.allResult
                    if (typeof obj.allResult !== "string") {
                        allResult = allResult.join('#')
                    }
                    _newObj_.showAnser = _newObj_.showAnser.replace(_newObj_.showContent, '')
                    _newObj_.impartAnser = TAndF + ',' + allResult
                    val.push(_newObj_)
                })
                return val
            },

chrome测试正常,返回非[]
forEach的执行顺序是否跟机型、浏览器有关?

阅读 1.1k
avatarAI BotBETA

JavaScript 的 forEach 循环是按照数组的顺序同步执行每个元素的。这意味着它不会并行执行,而是会等待每个循环都完成后再进行下一个循环。因此,你看到的返回结果是空数组 [] 的问题应该不是由于 forEach 的异步行为导致的。

在你的代码中,forEach 循环遍历 initData 数组的每个元素,并依次执行一系列操作。这些操作包括创建新的对象 _newObj_,对其进行一些处理,然后将新对象添加到 val 数组中。

由于 forEach 是同步执行的,所以你应该期望在循环结束时获得一个包含所有新对象的数组。这个结果应该与你在 Chrome 中看到的正常结果一致。

然而,你提到在生产环境中得到的是空数组。这可能是由于一些其他因素导致的,例如:

  1. 在生产环境中,initData 可能是空的或者未定义。在这种情况下,forEach 会直接返回,不会执行任何循环,因此 val 仍然是空的。
  2. 在生产环境中,可能有其他的代码或操作改变了 val 数组。这可能包括其他部分的代码、异步操作、或者浏览器/设备的特定行为。
  3. 你可能在不同的环境(例如开发环境和生产环境)中运行了不同的版本的 JavaScript 引擎。这可能导致一些微妙的差异,尽管 forEach 的基本行为应该是相同的。
  4. 在某些情况下,JavaScript 的行为可能会受到浏览器或设备的影响。例如,如果浏览器或设备的 JavaScript 引擎对某些特定的代码或操作进行了优化,可能会导致不同的结果。

为了解决这个问题,我建议你检查一下生产环境中的 initData 是否正常,以及是否有其他代码可能改变了 val 数组。你也可以尝试在不同的环境或不同的设备上测试你的代码,看看问题是否仍然存在。如果问题仍然存在,你可能需要进一步调试你的代码,看看是否有其他因素影响了结果。

2 个回答

forEach是同步任务,所以就不要老盯着他看了,可以看看其他的地方。

handleDealData返回的val是空数组,val是根据initData循环来的,所以可以看下initData是不是空。

另外,console打印的是快照,也就是你点击展开显示的值和你打印时的值可能不一样(中间你修改了这个数据),所以,可以猜测也有可能是后面更改了val

一、关于 forEach 及其变化

forEach 是同步的,这里的代码抽象一下,可以看到是这个结构:

const newArray = [];  // 产生一个空数组
oldArray.forEach(() => {
    const aObj = ..;
    newArray.push(aObj); // 每次循环插入一个数据
});
// 得到有数据的 newArray

这个结构可以直接使用 .map 来实现,即把 .forEach() 变更为 .map

const newArray = oldArray.map(() => {
   const aOjb = ...;
   return aObj
});

如果处理过程中存在 if 分支,并不是每次都会 push,那可以在 map 前(或后)使用 filter,来过滤数据。

参阅:JavaScript 数据处理 - 列表篇

二、关于 console.log

console.log 输出的是一个对象,而这个对象在实际渲染输出的时候,使用的是终值,并不一定是 console.log 执行时的值。

如果需要打印如当时的信息,最好是通过 JSON.stringify 或者是选择一部分属性(值)拼接成字符串(用模板字符串比较方便)来显示。注意使用 JSON.stringify 处理对象的时候可能需要处理循环引用问题。

比如

console.log("initData --->", JSON.stringify(initData, null, 2));
推荐问题
宣传栏