V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
thisiscoder
V2EX  ›  问与答

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

  •  
  •   thisiscoder · 2019-01-30 13:54:08 +08:00 · 2624 次点击
    这是一个创建于 2119 天前的主题,其中的信息可能已经有所发展或是发生改变。

    问题描述

    在我们的项目中,前后台使用 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 内存不在继续上涨

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

    不出问题见鬼了
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1775 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 16:46 · PVG 00:46 · LAX 08:46 · JFK 11:46
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.