有没有人有 vue 中使用 websocket 获取数据后使用 vue.set 渲染数据导致内存溢出的经历?

2019-01-30 13:54:08 +08:00
 thisiscoder

问题描述

在我们的项目中,前后台使用 websocket 连接,整个项目使用的 vue 框架。websocket 后台传输频率为4 次 /s,每次的数据量为2KB。前台使用 onmessage 方法接收到数据之后进行处理并使用 this.$set()方法将数据更新进数组中。在这个过程中出现了内存泄露的问题,表现形式为 chrome 内存急剧升高。

自己尝试过哪些方法

在百度和 google 之后,并经过自己的测试,发现 Vue 过于的 this.$set 方法会导致内存泄漏,而直接赋值进行替换则不会,于是将所有的 this.$set 方法更新数据改为了重新复制,发现有效降低了内存泄露的问题。但是并没有完全解决。在测试中,我将 websocket 的 onmessage 方法全部注释掉之后,发现 chrome 内存上涨的情况于前面修改之后上涨的速度一致。当将 websocket 整个注释掉之后 chrome 内存才不再上涨。

相关代码

这是处理数据的逻辑

            function onMessage(evt, containerName) {
                var containerIndex = vm.containerJson[containerName];
                if (!vm.flaginit[containerIndex]) {
                    try {
                        var request = JSON.parse(evt.data);
                    }catch (e) {
                        console.log(e);
                        return false;
                    }
                    var newIndex = containerIndex;
                    for (var i = 0; i < vm.pageContainer.length; i++) {
                        if (vm.pageContainer[i].Name == containerName) {
                            newIndex = i;
                            break;
                        }
                    }
                    vm.$set(vm.dynaDatas, containerIndex, request);
                    console.log(request);
                    if (request.msg != 'Open') {
                        if (vm.pageContainer[newIndex].Type === "remote" || vm.pageContainer[newIndex].Type === "data") {
                            if (request.Live != undefined) {
                                that.circleId[newIndex] = 0; //设置圈次索引值为 0,不然实时数据过来以后,被选中的圈次显示错误(不只第一圈被选中)
                                that.$set(that.stopOrStart, containerIndex, 'true');
                                that.clickButton(newIndex, true);
                                that.realTimePlayList(vm.pageContainer[newIndex].Name, request.Live, playListNum, 1, newIndex);
                                that.timebar[containerIndex] = that.$refs.progress[0].offsetWidth; //进度条的长度
                                clearInterval(that.PlayBackMode[containerIndex]);
                                var name = that.pageContainer[newIndex].Name;
                                // that.PlayBackMode[containerIndex] = setInterval(function () {
                                //     // that.getPlayList(name, request.Live, playlistsix, 1, containerIndex);
                                // }, 5000);
                                that.pageContainer[newIndex].showData = "true";//数据列表显示数据
                            }
                            else {
                                if (request.data != "{}" && request.statuscode == "200" && request.msg != "Pause" && request.data.Time != undefined) {
                                    if (request.data.Time != undefined) {
                                        vm.dataTime[containerIndex] = request.data.Time;//h5 显示的数据时间
                                        vm.noData[containerIndex] = new Date(request.data.Time.split("-")[0].split(":").join("-") + ' ' + request.data.Time.split("-")[1]).getTime();
                                        vm.shipTime[containerIndex] = formatDuring(vm.noData[containerIndex] - standardTime);
                                    }
                                    if (vm.pageContainer[newIndex].select == "true") { //回放模式
                                    var data = [vm.test];
                                    console.log(vm.timeBar[0]);
                                    if (data.length != 0) {
                                        data[vm.activeTimeIndex[containerIndex]].Active =
                                            (vm.noData[containerIndex] - 1502727683750) / (1502727683779 - 1502727683750);
                                        //当前圈次数据段最后一段和下一圈次数据段是连续的
                                        if (vm.timeBar[containerIndex] == "4" && data[data.length - 1].Active >= data[data.length - 1].End) {
                                            vm.websocket[containerIndex].send("Pause");
                                            that.$set(that.stopOrStart, containerIndex, 'false');
                                            that.clickButton(newIndex, false);
                                        }
                                    }

                                    function beforeTimeEnd(m) {//递归调用,更改当前间隔时间的前一段,状态为播放结束
                                        if (m <= -1) {
                                            return 1
                                        } else {
                                            data[m].Active = data[m].End - 0;
                                            return beforeTimeEnd(m - 1);
                                        }
                                    }

                                    function afterTimeStart(m) {//递归调用,更改当前间隔时间的后一段,状态为未播放
                                        if (m >= data.length) {
                                            return 1
                                        } else {
                                            data[m].Active = data[m].Start;
                                            return afterTimeStart(m + 1);
                                        }

                                    }

                                    for (var m = 0, l = data.length; m < l; m++) {
                                        if (data[vm.activeTimeIndex[containerIndex]].Active >= data[m].Start && data[vm.activeTimeIndex[containerIndex]].Active <= data[m].End) {
                                            data[m].Active = data[vm.activeTimeIndex[containerIndex]].Active;
                                            that.activeTimeIndex[containerIndex] = m;
                                            beforeTimeEnd(m - 1);
                                            afterTimeStart(m + 1);
                                        }
                                    }
                                    data = null;
                                    startTimeStamp = null;
                                    endTimeStamp = null;
                                }
                                else if (request.data == "") {
                                    var circle = vm.pageContainer[newIndex].listData[0].Circle[vm.timeBar[containerIndex]];
                                    var data = vm.pageContainer[newIndex].listData[0].Circle[vm.timeBar[containerIndex]].Data;
                                    if (data[vm.activeTimeIndex[containerIndex]].Active > data[data.length - 1].Start) {
                                        if (vm.timeBar[containerIndex] == "4" && request.data == "") { //判断当前容器第 5 圈最后一段数据(不等于 End 的情况下)播放完毕,向后台发送停止命令
                                            vm.websocket[containerIndex].send("Pause");
                                            that.$set(that.stopOrStart, containerIndex, 'false');
                                            that.clickButton(newIndex, false);
                                        } else {
                                            that.$set(that.stopOrStart, containerIndex, 'false');
                                            that.clickButton(newIndex, false);
                                            circle.select = "false";
                                            vm.timeBar[containerIndex]++;
                                            that.circleId[containerIndex] = vm.timeBar[containerIndex];//容器对应圈数的索引
                                            vm.activeTimeIndex[containerIndex] = 0;
                                            that.timebar[containerIndex] = that.$refs.progress[0].offsetWidth; //进度条的长度
                                            circle.select = "true";
                                            that.$set(that.stopOrStart, containerIndex, 'true');
                                            that.clickButton(newIndex, true);
                                            if (data.length != 0) {
                                                vm.nextCircvarime[containerIndex] = Math.round(data[0].Start * 90 * 60);
                                                vm.nextCircvarimeHour[containerIndex] = parseInt(vm.nextCircvarime[containerIndex] / 3600);
                                                vm.nextCircvarimeMin[containerIndex] = parseInt(vm.nextCircvarime[containerIndex] % 3600 / 60);
                                                vm.nextCircvarimeSec[containerIndex] = parseInt(vm.nextCircvarime[containerIndex] % 3600 % 60);
                                                vm.nextCircvarimeH[containerIndex] = Number(vm.nextCircvarimeHour[containerIndex]) + Number(circle.Start[1].split(":")[0]);
                                                vm.nextCircvarimeM[containerIndex] = Number(vm.nextCircvarimeMin[containerIndex]) + Number(circle.Start[1].split(":")[1]);
                                                vm.nextCircvarimeS[containerIndex] = Number(vm.nextCircvarimeSec[containerIndex]) + Number(circle.Start[1].split(":")[2]);
                                                if (vm.nextCircvarimeS[containerIndex] > 60) {
                                                    vm.nextCircvarimeS[containerIndex] = vm.nextCircvarimeS[containerIndex] - 60;
                                                    vm.nextCircvarimeM[containerIndex] = vm.nextCircvarimeM[containerIndex] + 1;
                                                } else {
                                                    if (vm.nextCircvarimeM[containerIndex] > 60) {
                                                        vm.nextCircvarimeM[containerIndex] = vm.nextCircvarimeM[containerIndex] - 60;
                                                        vm.nextCircvarimeH[containerIndex] = vm.nextCircvarimeH[containerIndex] + 1;
                                                    } else {
                                                        if (vm.nextCircvarimeH[containerIndex] > 23) {
                                                            vm.nextCircvarimeH[containerIndex] = 0;
                                                        } else {
                                                            vm.nextCircvarimeH[containerIndex] = vm.nextCircvarimeH[containerIndex];
                                                        }
                                                        vm.nextCircvarimeM[containerIndex] = vm.nextCircvarimeM[containerIndex];
                                                    }
                                                    vm.nextCircvarimeS[containerIndex] = vm.nextCircvarimeS[containerIndex];
                                                }
                                                vm.nextCircvarime[containerIndex] = vm.nextCircvarimeH[containerIndex] + ":" + vm.nextCircvarimeM[containerIndex] + ":" + vm.nextCircvarimeS[containerIndex] + ":" + "000";
                                                vm.nextstartNextTime[containerIndex] = circle.Start[0] + "-" + vm.nextCircvarime[containerIndex];
                                                if (vm.pageContainer[newIndex].Type === "remote" || vm.pageContainer[newIndex].Type === "data") {
                                                    vm.websocket[containerIndex].send("Play" + ";" + vm.nextstartNextTime[containerIndex] + ";");
                                                    vm.pageContainer[newIndex].showData = "true";
                                                }
                                            }
                                        }
                                    } else {
                                        vm.activeTimeIndex[containerIndex]++;
                                        vm.stageTime[containerIndex] = Math.round(data[vm.activeTimeIndex[containerIndex]].Start * 90 * 60);
                                        vm.stageTimeHour[containerIndex] = parseInt(vm.stageTime[containerIndex] / 3600);
                                        vm.stageTimeMin[containerIndex] = parseInt(vm.stageTime[containerIndex] % 3600 / 60);
                                        vm.stageTimeSec[containerIndex] = parseInt(vm.stageTime[containerIndex] % 3600 % 60);
                                        vm.stageTimeH[containerIndex] = Number(vm.stageTimeHour[containerIndex]) + Number(circle.Start[1].split(":")[0]);
                                        vm.stageTimeM[containerIndex] = Number(vm.stageTimeMin[containerIndex]) + Number(circle.Start[1].split(":")[1]);
                                        vm.stageTimeS[containerIndex] = Number(vm.stageTimeSec[containerIndex]) + Number(circle.Start[1].split(":")[2]);
                                        if (vm.stageTimeS[containerIndex] > 60) {
                                            vm.stageTimeS[containerIndex] = vm.stageTimeS[containerIndex] - 60;
                                            vm.stageTimeM[containerIndex] = vm.stageTimeM[containerIndex] + 1;
                                        } else {
                                            if (vm.stageTimeM[containerIndex] > 60) {
                                                vm.stageTimeM[containerIndex] = vm.stageTimeM[containerIndex] - 60;
                                                vm.stageTimeH[containerIndex] = vm.stageTimeH[containerIndex] + 1;
                                            } else {
                                                if (vm.stageTimeH[containerIndex] > 23) {
                                                    vm.stageTimeH[containerIndex] = 0;
                                                } else {
                                                    vm.stageTimeH[containerIndex] = vm.stageTimeH[containerIndex];
                                                }
                                                vm.stageTimeM[containerIndex] = vm.stageTimeM[containerIndex];
                                            }
                                            vm.stageTimeS[containerIndex] = vm.stageTimeS[containerIndex];
                                        }
                                        vm.nextTime[containerIndex] = vm.stageTimeH[containerIndex] + ":" + vm.stageTimeM[containerIndex] + ":" + vm.stageTimeS[containerIndex] + ":" + "000";
                                        vm.CircleStartTime[0] = vm.CircleStartTime[0];
                                        vm.startNextTime[containerIndex] = vm.CircleStartTime[0] + "-" + vm.nextTime[containerIndex];
                                        vm.websocket[containerIndex].send("Play" + ";" + vm.startNextTime[containerIndex] + ";");
                                        vm.pageContainer[newIndex].showData = "true";
                                    }
                                }
                            }
                            var detailData = [];
                            var k = 0;
                            if (request.data != undefined) {
                                if (request.data.Params != undefined) {
                                    for (var j in request.data.Params) {
                                        var dataObj = {};
                                        if (j != "Image") {
                                            dataObj.name = j;
                                            dataObj.content = request.data.Params[j].split(";");
                                            detailData[k++] = dataObj;
                                        }
                                    }
                                    //数值数据刷新
                                    for (var j = 0; j < vm.pageContainer[newIndex].Topic.length; j++) {
                                        for (var k = 0; k < detailData.length; k++) {
                                            if (vm.pageContainer[newIndex].Topic[j].Codename["0"].Content == detailData[k].name) {
                                                var dataObj = {};
                                                dataObj.code = detailData[k].content[0];
                                                dataObj.result = detailData[k].content[1];
                                                dataObj.mean = detailData[k].content[2];
                                                dataObj.beyond = detailData[k].content[3];
                                                vm.$set(vm.pageContainer[newIndex].Topic[j], "dynData", dataObj);
                                            }
                                        }
                                    }
                                } else {
                                    request.data = detailData;
                                }
                            }
                        }
                    }
                }

注释掉 onmsaage 方法依旧继续上涨

  // name.onmessage = function (evt) {
            //     // onMessage(evt, containerName);
            // };

期待的结果

希望在使用 websocket 的过程中 chrome 内存不在继续上涨

2618 次点击
所在节点    问与答
3 条回复
arslion
2019-01-30 14:09:00 +08:00
为什么要这样大段大段冲击波式地写代码?
没有冒犯的意思,是真的不理解
CDL
2019-01-30 14:15:46 +08:00
这一大坨的代码... 看不下去
vigossliao
2019-01-30 14:44:30 +08:00
不多说 这个代码看起来真难受

不出问题见鬼了

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/531854

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX