V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐关注
Meteor
JSLint - a JavaScript code quality tool
jsFiddle
D3.js
WebStorm
推荐书目
JavaScript 权威指南第 5 版
Closure: The Definitive Guide
SkYouth
V2EX  ›  JavaScript

关于 setInterval 和 setTimeout 结合使用,内存溢出的问题

  •  
  •   SkYouth · 2019-08-19 16:56:19 +08:00 · 3964 次点击
    这是一个创建于 1705 天前的主题,其中的信息可能已经有所发展或是发生改变。

    场景:要求一个柱状图柱子动态变化,将柱状图先正常渲染,渲染后执行下面的定时任务,先将值清空再重新赋值原来的值(这种无聊的变化是产品要求的。说动起来炫一点)。

    问题:如果浏览器停留在此页面时候,内存正常(谷歌 F12-->Memory), 但是如果将浏览器切换到其他标签页(假如打开一个百度,停留在百度页),内存会一直增长,直至崩溃


    代码:

    this.intervalId = setInterval(() => {
    	let {myCharts} = this
    	let options = this.myCharts.getOption()
    	let serData = JSON.parse(JSON.stringify(options.series))
        // 把所有数据清空
    	for (let i = 0; i < serData.length; i++) {
    		serData[i].data = null
    	}
        myCharts.setOption({
        	series: serData
    	})
    	setTimeout(() => {
        	// 重新赋值
    		myCharts.setOption({
    			series: options.series
    		})
    	}, 800)
    }, 6000)
    

    在网上试了一个例子: https://echarts.baidu.com/examples/editor.html?c=gauge-car

    在编辑框最下面改为

    setInterval(function (){
        option.series[0].data[0].value = 0;
        option.series[1].data[0].value = 0;
        option.series[2].data[0].value = 0;
        option.series[3].data[0].value = 0;
        myChart.setOption(option,true);
        setTimeout(function() {
            
        option.series[0].data[0].value = (Math.random()*100).toFixed(2) - 0;
        option.series[1].data[0].value = (Math.random()*7).toFixed(2) - 0;
        option.series[2].data[0].value = (Math.random()*2).toFixed(2) - 0;
        option.series[3].data[0].value = (Math.random()*2).toFixed(2) - 0;
        myChart.setOption(option,true);
            
        }, 800);
    },2000);
    

    打开 f12 切走页面看内存。

    问: 有知道原因的同学吗? 我这边一开始想的是内存释放的问题, 那页面激活和未激活为啥会不一样?

    13 条回复    2019-08-20 09:46:57 +08:00
    JK9993
        1
    JK9993  
       2019-08-19 17:07:25 +08:00
    mac 74.0.3729.169 没这个问题
    imbacc
        2
    imbacc  
       2019-08-19 17:11:07 +08:00
    不清除计时器? j = serData.length 吧
    SkYouth
        3
    SkYouth  
    OP
       2019-08-19 17:13:11 +08:00
    @JK9993 百度 echarts 那个例子增长会很慢。 我的那段代码在我本地差不多每次 interval 就会增加 15M 左右…… 好几个同事的 pc 这样,window 环境应该是必然增长
    SkYouth
        4
    SkYouth  
    OP
       2019-08-19 17:15:20 +08:00
    @imbacc 问题不出在 serData.length,删除 setTimeout 即使切换了标签页,内存也稳定。setInterval 会在页面销毁时候清除。
    lenonrade
        5
    lenonrade  
       2019-08-19 17:16:57 +08:00
    建议用 log 看看执行顺序,用 Echarts 做过一个柱状图循环显示的小 demo,不知你具体需求是啥
    xenme
        6
    xenme  
       2019-08-19 18:00:10 +08:00 via iPhone
    猜一下是不是每次 setinterval 都保存一份 local 变量,然后爆了。

    百度那个只是改变了外部变量的属性。和动画啥的。
    ashong
        7
    ashong  
       2019-08-19 18:39:37 +08:00
    myCharts.setOption 迭代造成的溢出
    momocraft
        8
    momocraft  
       2019-08-19 18:44:20 +08:00
    也许 inactive 页面推迟了一些事件,正常会执行完释放的东西没被释放

    也许用 page visibility API 在页面不活动时暂停计时
    tomato3
        9
    tomato3  
       2019-08-19 18:45:46 +08:00 via Android
    开发工具 snapshot 一下 memery,对比一下多了哪些对象
    SkYouth
        10
    SkYouth  
    OP
       2019-08-20 08:57:52 +08:00
    @ashong 嗯 应该是 myecharts 的问题,不过停留在页面的时候, 内存不会增加,比较诧异。
    SkYouth
        11
    SkYouth  
    OP
       2019-08-20 08:58:30 +08:00
    @momocraft 现在的临时解决办法就是通过监听 visibilitychange 来暂停计时。
    SkYouth
        12
    SkYouth  
    OP
       2019-08-20 08:58:47 +08:00
    @tomato3 好,谢谢 我还真没认真比较过
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   1217 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 23:54 · PVG 07:54 · LAX 16:54 · JFK 19:54
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.