美文网首页
Websocket, SetTimeout 与页面崩溃

Websocket, SetTimeout 与页面崩溃

作者: 李书文 | 来源:发表于2017-05-09 11:02 被阅读577次

问题

用户在RDP的使用中有时候会用鼠标在打开的PDF文档中拖动选择大块的文字和图片。当用户鼠标拖动到PDF窗口的最外侧时,这个时候选择会自动进行下去(我们平时选择网页中的文字也有这个经验)。当这种情况发生一小会儿的时候,页面就Freeze了,再等一会儿页面就崩溃了。FireFox、Chrome、IE都会有这个页面崩溃或者Javascript影响效率是否关闭的提示。

起因

这个问题的起因可以分为几部来说:

  1. Javascript前段处理所有RDP的数据都是单线程的(为什么不用多线程?为什么不用Worker?因为Worker根本没法操作Canvas,而且Worker的PostMessage即使是传输Object Reference的时候也有严重的问题,或者我的写法有问题)
  2. 当用户做出如上的动作的时候,RDS会发送大量的Update Order到前段
  3. 前段接收到这些Orders之后需要对Canvas进行大量的更新操作
  4. 因为这些大量的操作导致前段页面根本没有时间来响应用户的输入,这就是Freeze的原因
  5. 因为没有办法响应用户的输入,这个大量刷新的操作就无从打断,后续还会发来海量的Update Orders
  6. 浏览器在检测到这个页面一直在闷头计算而不响应用户输入,而且占用了大量的内存,就让它挂掉了

解决方案

解决方案是从Stackoverflow上找的
Websocket connection hangs randomly in Safari iOS

解决方法很简单,在websocket的onmessage的回掉函数中使用SetTimeout,如下:

websocket.onmessage = function(event) { 
        setTimeout(function() {
            handle_message(event);
        }, 0); 
    };

如果了解Javascript事件循环的话就会明白这个方案很高明的让浏览器的底层来承担了海量数据处理的规划问题。通过将处理事件塞入Timeout队列来避免了前端无法响应用户输入的问题。这就给了用户可以通过输入来打断这个无限循环的问题。

后记

其实这个问题到这里并没有完美的解决。最好的解决方案应该是让Javascript可以真正的支持多线程。这个需要有Shared Memory的支持。这个个新的特性可能会加入ES7中,相关的参考:
前端开发信息汇总 中的 初探新的 JavaScript 并行特性
我自己写了一个的实验项目对Shared Memory进行了测试,效率之高几乎和Native应用有一拼。


End

相关文章

网友评论

      本文标题:Websocket, SetTimeout 与页面崩溃

      本文链接:https://www.haomeiwen.com/subject/mmebtxtx.html