使用setTimeout轮询请求数据,12小时以上导致页面卡顿

经过大家的 讨论和长时间测试发现:长时间轮询请求接口会出现短暂的pending状态,页面上的事件失效。等接口响应后又正常了。接口响应又很快。

是个监测系统,目前是轮询请求(3s一次)是可能会导致页面卡。
有什么好办法吗。暂时除了websocket
image.png

阅读 16.9k
8 个回答

延时器 setTimeout 如果不需要中断延时的话,是没必要清除的。
这段代码没有什么问题。
可以在不卡顿和卡顿的时候分别录一个内存快照,对比下内存的使用,有可能是别的地方内存没有释放,比如历史数据堆积在数组里什么的。

chrome 录制堆内存快照的方法:
F12 打开开发者工具 -> Memory -> 点击Take heap snapshot(左上角的圆点按钮) 。获取快照之后按 Retained Size 从高到低排序,重点是要对比卡顿和不卡顿的页面上同一个 Constructor 的子类和实例所占用的总内存差异。

但这里 只能定位到构造函数名 ,而你不一定知道这个构造函数是在哪里定义的,如果是我的话会顺着 this.handleOnline 的执行链一路向下排查,有经验的人无须内存快照就能找到问题所在。
我觉得可能性最大的两种诱因:

  1. 某处或多处一直向一个数组追加数据;
  2. 某处或多处一直添加 HTML 内容。

因为很少有前端会开发长时间持续运行的网页,在时间维度上的资源管理就不会太在意,崩溃了大不了刷新就行。


this.handleOnline 本身没有问题,那么问题可能出在 this.refreshSensorTablle ,需要继续排查……路途可能还很遥远呐!

const sleep = time => new Promise(resolve => setTimeout(resolve, time));

async run() {
    while(true){
        await sleep(3000);
        await this.handleOnline();
    }
}

最后的:
await this.handleOnlineTimer()
改成:
this.handleOnlineTimer()
试试. 是这个原因么

吧setTimeOut换成 setInterval 试试看

其实我在想是不是可以把清除的定时器 放在外面呢?
每次执行当前的方法的时候 先清除定时器、保证当前轮询的事件始终保持一个?

有可能都不是前端问题,12小时后,本身系统内存不足,导致前端页面卡顿

感觉和轮询本身没有关系,可能是渲染图表时候的问题。比如之前的数据没有及时清理或者图表实例没有清除,导致刷新图表的时候数据始终在内存中叠加造成的内存泄漏问题。

还有如果渲染图表的数据过大,建议通过数据渐进式渲染,不要一次性把所有数据传给图表,一般的图表框架应该都提供这种方式。

不过具体原因还是要排查才行。

持续测试后发现还是会有一些问题,长时间后还是会卡,有可能是浏览器机制问题,感觉需要唤醒一样,知识储备欠缺。暂时放弃。换了SignalR了,是WebSockets,LongPolling,serverSentEvents。三个的封装,目前还在测试中。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题