背景
最近开发一个页面碰到一个需求,需要对部分数据需要实时更新状态,面对这样子的场景,我们通常有以下几个方案:
- 轮询,利用setTimeout定时轮询
- WebSocket,利用长链接保持与服务通讯
- SSE,服务端推送机制
是什么
我们先简单认识一下这三者的区别:
轮询
轮询就是利用setTimeout的定时器,定时向服务器发起请求,代码如下:
1 | let timeout = 0; |
缺点
- 无用请求过多,可能每次请求返回的内容都是相同
- 实时性不可控,如果内容更新了,但是页面无法及时更新
WebSocket
针对上面轮询的缺点,WebSokcet长链接就能很好解决,如:
- 建立链接后,当服务器发现数据发生变化后才返回
- 可控性高,客户端和服务端都可以互相通信
具体实现代码如下:
1 |
|
缺点
可能实现方案对于一个页面数据更新有点太重了,主要包括以下几点:
- 需要有完整链路认证,如:鉴权、登录等
- 心跳机制实现,前后端都需要设置
- 前后端需要规定数据返回规范
- 服务端需要日志记录
SSE服务端推送
SSE全称Server-sent Events,是HTML 5 规范的一个组成部分,它主要由两部分组成:
- 第一部分是服务端和浏览器的通讯协议
- 第二部分是前端需要利用
EventSource
去监听返回数据
对比WebSocket:
SSE | WebSocket |
---|---|
单向:仅服务端能发送消息 | 双向:客户端、服务端双向发送 |
仅文本数据 | 二进制、文本都可 |
常规HTTP协议 | WebSocket协议 |
实现一个SSE代码如下:
浏览器:
1 |
|
服务端:
1 | const http = require('http') |
缺点
兼容性问题,但是目前绝大部分浏览器是支持的,如果不支持可以采用降级方案——轮询
会长期占用一个http链接,
- 可能会导致浏览器(chrome最大http请求数是6)无法发起其他请求,这里注意是一个坑,需要设置一个超时时间,如果长时间无返回数据更新可以关闭链接
- 解决方案,升级到http2协议可解决http请求数限制问题,放到后面《如何搭建http2网站》讲解
客户端无法主动向服务器发起请求,可能造成后续问题定位难点
总结
前端实时更新需求,有多个解决方案,下面进行总结:
目前最常用的轮询,是最稳定的,但是却无法做到实时
WebSocket可以实时,但是需要服务端和客服端长期保持一致,如果哪一方断了将无法继续
SSE是服务推送,可以满足大部分场景,但是也需要谨慎使用,避免占用过多链接导致其他无法发送请求
参考资料
- 本文作者: Qborfy
- 本文链接: https://www.qborfy.com/today/20230223.html
- 版权声明: 本博客所有文章除特别声明外,均采用 MIT 许可协议。转载请注明出处!