JS如何解决内存泄漏页面崩溃问题(JS,开发技术)

时间:2024-05-04 19:52:05 作者 : 石家庄SEO 分类 : 开发技术
  • TAG :

这篇“JS如何解决内存泄漏页面崩溃问题”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“JS如何解决内存泄漏页面崩溃问题”文章吧。

死去的页面突然攻击我?

因为项目本身过于庞大,且用户反馈不特定页面崩溃,这使得问题定位难度较大。

经过团队的讨论认为可能是该用户的组织架构接口数据量过大,当数据到达页面后需要经过递归处理,导致内存不足,且通过调试发现并非初次调用该接口就会导致崩溃,而是需要多次调用才会出现该问题。

而且在调试的过程中还发现因数据量过大,该接口需要长达 30s 的时间才能返回。而这么长的时间用户可能已经离开这个页面了。我们尝试以这个场景进行操作发现,用户离开页面并没有取消已经发出的请求,当该请求响应后会导致内存占用飙升。

因该接口为项目全局接口,经过讨论我们决定先修复这个离开页面不取消请求的问题,测试能否解决崩溃问题。

JS如何解决内存泄漏页面崩溃问题

陷入僵局

当我们在离开页面时取消未完成的请求后,测试反馈仍然会不定时崩溃,此时的我们有点无从下手了。因为我们发现问题貌似有点大了。

此时我们已经开始怀疑出现了内存泄漏,于是我们祭出了 chrome-devtool 使用 Memory 来进行内存占用分析。

JS如何解决内存泄漏页面崩溃问题

经过内存分析发现,内存中存在大量的分离元素未能及时回收。我按照内存快照的指引开始了漫长的修改。两天的修改后发现,虽然修复了不少的问题,但是仍然不能有效的降低页面的内存占用,每当我们跳转新的页面时某些页面仍然不能正常释放。此时我为了高效定位问题,开始使用绝招——删代码。

  • 将页面中的组织架构树删除——内存占用没降下来...

  • 将页面的列表删除——很棒空页面果真降下来了

  • 将组织架构树加上,列表删除——内存又起来了...

此时的我认为组织架构树的写法有问题,所以花了两天的时间过了一遍组织架构树的代码,未发现有什么异常的地方。

为了确认是组织架构树的问题还是页面列表的问题,我在项目中新建了两个空白的路由页面。在这个页面中单独使用这两个组件,都没有问题。

问题陷入了僵局...

垂死病中惊坐起

在我们修复这个问题的期间,另一个用户也反馈了相同的问题过来,不过用户说他用的是edge浏览器。此时同事说edge好像可以撑的更久一点。????哇,真的吗?难道和浏览器有关系?

于是我又打开了edge浏览器,点开了devtool点开了Memory...哎?这是什么

JS如何解决内存泄漏页面崩溃问题

edge的devtool这么好吗,专门有独立的标签用来查找分离的元素啊,蛮人性化的嘛。可是这和chrome不一样呀,咋用呢?(戳这里)

JS如何解决内存泄漏页面崩溃问题

它真的好智能,竟然已经把所有泄漏的dom按照结构组织好了,这样就不用我再从一堆内存信息中一个个找它们的关联关系了。

从上图我发现原来是有一个全局的tip()方法导致了整个页面没能正常回收,用户每进一次这个页面就会在内存里多一份这个页面的dom节点。而这个页面又有完整的组织架构树,组织架构树又很大...

查看了tip()方法的源码发现,这是一个全局的指令,这个指令每次都会创建一个新的tip对象,而这个tip对象与页面上的dom节点关联,且永远不会被销毁。

类似的问题在列表中有个对表格行拖拽排序的功能,使用了第三方包sortablejs而未调用destory()方法销毁sortable 实例,进而导致表格与页面也未能正确释放。

勿以善小而不为

到此,大概的原因已经明确了。未及时销毁的无用对象导致了大面积的内存泄漏,叠加用户的配置较低(8G内存,且开启了很多页面),导致了页面的崩溃。

类似以上的问题在本次修复中还发现不少,如:

  • 公共弹窗组件将传入的子组件持有,在关闭弹窗后未能销毁子组件。

  • 全局的EventBus实例未及时调用$off方法销毁事件,而事件回调与页面又产生关联(如:$refs、$parents)

  • 组件接受来自页面的方法,而该组件未能在页面离开时销毁(如在组件内将组件的this绑定在window上),导致整个页面不能释放

  • 为了在页面resize时能够调节echarts大小,在window上绑定了resize回调,离开页面时为清除resize事件

  • 组件实例化时在document上绑定click事件后,销毁组件时为清除click事件

以上的每一个问题都是小问题,仅仅是因为没用在beforeDestroy中调用Element.removeEventListener()或者未调用destroy()方法。但是会导致很大的后患。

修复后的页面已经能够达到较为正常的内存占用了,在此给大家放一张测试同学提供的修复前后的内存占用对比图,相较于修复前的内存占用只增不减(峰值4G,然后崩溃)到现在的能及时回收(最复杂的页面峰值500M,普通页面100M以内),已经有了极大的提升。

JS如何解决内存泄漏页面崩溃问题

JS如何解决内存泄漏页面崩溃问题

修改参考

consthandleResizeWindow=()=>{myChart.resize();}window.addEventListener("resize",handleResizeWindow);this.$once('hook:beforeDestroy',()=>{myChart.dispose()//销毁echart实例window.removeEventListener('resize',handleResizeWindow)})
created(){window.removeEventListener('beforeunload',this.closePage)},...beforeDestroy(){window.removeEventListener('beforeunload',this.closePage)}
mounted(){this.$eventBus.$on("eventName",this.handleEvent);this.$once('hook:beforeDestroy',()=>{this.$eventBus.$off('eventName',this.handleEvent)})}

以上就是关于“JS如何解决内存泄漏页面崩溃问题”这篇文章的内容,相信大家都有了一定的了解,希望小编分享的内容对大家有帮助,若想了解更多相关的知识内容,请关注亿速云行业资讯频道。

本文:JS如何解决内存泄漏页面崩溃问题的详细内容,希望对您有所帮助,信息来源于网络。
上一篇:GO语言包管理工具go mod及包应用实例分析下一篇:

21 人围观 / 0 条评论 ↓快速评论↓

(必须)

(必须,保密)

阿狸1 阿狸2 阿狸3 阿狸4 阿狸5 阿狸6 阿狸7 阿狸8 阿狸9 阿狸10 阿狸11 阿狸12 阿狸13 阿狸14 阿狸15 阿狸16 阿狸17 阿狸18