当浏览器选项卡没有焦点时使用 Websocket 进行角冻结
Posted
技术标签:
【中文标题】当浏览器选项卡没有焦点时使用 Websocket 进行角冻结【英文标题】:Angular Freezing With Websocket When Browser Tab Doesn't Have Focus 【发布时间】:2020-09-02 08:47:31 【问题描述】:我们有一个 Angular 8 项目,它有一个带有恒定数据流的 websocket。数据存储在 clientInfo 对象中,更改会立即通过 service.clientInfo.variable 反映在页面中。唯一的问题是,当我转到浏览器中的另一个选项卡并返回该页面时,有时页面需要几秒钟才能赶上,并且在那之前一切都没有响应。
如果我让浏览器选项卡长时间处于非活动状态,我的所有组件都将被隐藏,整个选项卡将永久冻结,我必须重新打开它(chrome)。我注意到,如果我转到网站的另一部分没有显示来自 websocket 的数据,则不会发生这种情况。对我来说,这似乎是更改检测正在缓冲所有内容,并且在浏览器选项卡没有焦点时不进行任何 DOM 更改,最终耗尽内存。
我想我可以尝试使用文档的“visibilitychange”事件来检测浏览器选项卡何时被隐藏,然后设置一个显示/隐藏布尔值。我试图使用一个标志使用* ngif来隐藏显示WebSocket数据的部分,但是当标签丢失焦点时,NGIF不会及时隐藏它。
有什么简单的解决方案吗?我可以在某种程度上告诉Angular在Tab禁止处于活动状态时停止在ClientInfo对象上的更改检测吗?我以为我可以使用前面提到的可见性标志来将传入的WebSocket数据存储在不同的对象中,然后当标签重新归焦时,我可以将这些值与主要的ClientInfo对象合并,但我确定必须有更简单的解决方案。
编辑以更清楚地了解其设置方式:
这是我们服务中的 clientInfo 对象的简化版本,还有更多内容,但流是相关页面上显示的部分:
clientInfo =
streams: [
id: 1, count: 123 ,
id: 2, count: 456
]
;
然后页面会显示此数据(再次简化),如下所示:
<li *ngFor="let stream of service.streams">
stream.count
</li>
streams 值是我们服务中的一个 getter,设置如下:
get streams(): DataStream[]
if(this.clientInfo)
return this.clientInfo.streams;
return [];
我们使用getter的原因是因为路径实际上比clientInfo.streams长,为了简单起见我只是这样写。
websocket 发送增量更新,因此我们遍历流,检查 id 是否匹配,并更新计数。
提前致谢, 克里斯。
【问题讨论】:
您的场景有点不清楚,最好附上一段代码来解释您面临的问题。至于在浏览器选项卡切换或失去焦点时执行操作,您可以使用 @HostListener('blur', ['$event']) 【参考方案1】:抱歉,我想我的问题过于简化了。我省略了在 ngFor 循环中使用的 ngx-charts (https://github.com/swimlane/ngx-charts) 组件。当我在 clientInfo 对象中注释掉更新图形数据的代码时,页面停止冻结。
ngx-charts 一定一直在要求 d3 一遍又一遍地更新图表,但标签没有被聚焦。没有多少人会这样做,但我想要点是,当没人能看到你的标签时不要更新 ngx-charts。
【讨论】:
以上是关于当浏览器选项卡没有焦点时使用 Websocket 进行角冻结的主要内容,如果未能解决你的问题,请参考以下文章