Chrome 中当离开当前我写的 tab 时,内存居然增加了

不知道你是否在工作中遇到过,当你离开浏览器 tab 的时候,可能你去干其他事情去了,有可能你打开网页,下班的时候忘记关了,电脑也忘记关了,但很不幸的事,当你再次打开 tab 的时候发现页面已经崩溃了,或者页面变得比之前更卡了。

当我遇到这个问题的时候,我第一时间想到的是,内存泄露;于是我打开了内存分析工具,我足足分析了一个小时也没有发现内存存在泄露,每一次内存释放都能回到之前的内存量,于是我开始困惑了,于是我便开始分析代码,看了好一会儿也没发现有啥端倪。这个时候我便放下之前的方式,想想之前线上会不会存在这样的问题,于是我打开线上环境,进行了测试,但是还是一无所获。于是我告诉了测试,让测试测试之前的版本。哪天下班了,测试像往常一样操作,当再次上班的时候发现问题不存在。然后我便开始分析新增的代码,不知道找了多久,把所有的怀疑都验证了,都不是问题的关键。一次偶然的机会让我察觉到了问题的存在。

因为我是一直开着这个性能检测器的。我苦思冥想也想不出,我便一边百度一边思考;这次很意外,我思考的比较久,当我再次回到这个界面的时候,发现上面的 JS 推大小 居然变大了很多,但是不一会儿内存又回到了正常水平,于是我就开始怀疑是因为离开了这个页面导致的;接下来我便开始刻意离开页面,然后观察内存使用情况,发现果然如此。我们的代码逻辑是一直接收 base64 的照片,然后渲染出来,看起来就像一个视频,我们的 base64 的照片是设备上报来的,要想设备上报这些数据,需要使用串口跟设备建立连接。但是当我离开界面经过一段时间再次回来的时候,即便我断开与设备的连接,但是图像仍然一直在动,说明此时还有很多逻辑没有处理,一直被堆积,所以即便切断了来源,水还是一直在流,也就是离开页面以后水是流在蓄水池里面,并没有直接消化掉。基于这个结论我再次分析了代码,最后把代码锁定在下面这几行:

JavaScript 复制代码
// 模拟源源不断的水
setInterval(() => {
  console.log(i ++)
  requestIdleCallback(() => {
    console.log("这里处理图片的相关操作")
  })
}, 2000)

其中对图片的逻辑操作由于存在一定的逻辑,担心慢,也是因为出现过慢的情况(其实后面排查发现是设备导致的慢,跟我这边无关,只不过代码已经改了),于是我就想不要采用同步的方式执行,而是改成异步,但是我又不想使用 setTimeout ,于是想到使用这个 requestIdleCallback 来执行,但是我对这个 api 的理解仅仅停留在能调用的水平,不知道的是,这个 apitab 标签处于非激活状态下时,回调不会被执行。那在非激活状态下这些回调怎么处理呢,很简单就是将所有的回调存起来,当 tab 再次激活的时候执行。

其中 127 这个就是当从未激活到激活时迅速消化掉的日志。如果你的回调里面处理的逻辑不多,有时候你是察觉不到的,因为你切回来的瞬间几乎就能消化掉之前的。只有长时间处于非激活状态,你才能看出内存的变化。如果非要使用这个 api ,一定要配合这个 api 的第二个参数,也就是 option 。把代码改成下面这样就不会存在问题了,当然对于这种代码最好还是不要采用这样方式来解决。

JavaScript 复制代码
// 模拟源源不断的水
setInterval(() => {
  console.log(i ++)
  requestIdleCallback(() => {
    console.log("这里处理图片的相关操作")
    // 这里新增一个超时的参数
  }, {timeout: 100})
}, 2000)

如果这样,即便我们的 tab 处于非激活状态也会被执行。,当然这并非保险的做法,对于我的需求来说,最好不要使用这种办法,如果真的很费时,那么采用 setTimeout 就很不错。

由于我只是在 Chrome 中进行测试和操作,所以以上都是 Chrome 浏览器的,其他的浏览器需要当事人进行充分测试才能保证其正确性。

相关推荐
江城开朗的豌豆几秒前
JavaScript篇:移动端点击的300ms魔咒:你以为用户手抖?其实是浏览器在搞事情!
前端·javascript·面试
华洛7 分钟前
聊聊我们公司的AI应用工程师每天都干啥?
前端·javascript·vue.js
江城开朗的豌豆7 分钟前
JavaScript篇:你以为事件循环都一样?浏览器和Node的差别让我栽了跟头!
前端·javascript·面试
技术小丁9 分钟前
使用 HTML +JavaScript 从零构建视频帧提取器
javascript·html·音视频
漫谈网络28 分钟前
TypeScript 编译 ES6+ 语法到兼容的 JavaScript介绍
javascript·typescript·es6
bin91531 小时前
DeepSeek 助力 Vue3 开发:打造丝滑的日历(Calendar),日历_天气预报日历示例(CalendarView01_18)
前端·javascript·vue.js·ecmascript·deepseek
江城开朗的豌豆1 小时前
JavaScript篇:反柯里化:让函数'反悔'自己的特异功能,回归普通生活!
前端·javascript·面试
江城开朗的豌豆1 小时前
JavaScript篇:数字千分位格式化:从入门到花式炫技
前端·javascript·面试
十年砍柴---小火苗1 小时前
原生js操作元素类名(classList,classList.add...)
javascript·css·css3
JohnYan8 小时前
Bun技术评估 - 04 HTTP Client
javascript·后端·bun