参考文档:万字长文,一篇吃透WebSocket:概念、原理、易错常识、动手实践、WebSocket 教程
1 背景
有一个需求,需要实现实时通信的功能,如果有新消息,后端会主动发送请求告知前端有新消息,需要前端展示该新消息。
目前HTTP协议的话,只能支持客户端向服务器发出请求,服务器返回查询结果,做不到服务器主动向客户端推送信息。
或者,前端考虑定时向服务端发送请求(轮询),来判断是否有新消息,但是这种方式不太灵敏,而且可能前端发送的无用请求会很多。轮询的效率低,非常浪费资源(因为必须不停连接,或者 HTTP 连接始终打开)。
所以考虑WebSocket,服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对话,属于服务器推送技术的一种。
2 短轮询 & 长轮询
短轮询:服务器收到请求不管是否有数据都直接响应 http 请求。
长轮询:客户端向服务器发送Ajax请求,服务器接到请求后hold住连接,直到有新消息才返回响应信息并关闭连接,客户端处理完响应信息后再向服务器发送新的请求。
3 WebSocket概念
(1) Websocket 使用 ws 或 wss 的统一资源标志符(URI),其中 wss 表示使用了 TLS 的 Websocket。
如:
ws://echo.websocket.org
wss://echo.websocket.org
(2)创建链接的方式,WebSocket MDN
const websocket = new WebSocket(url[, protocols])
(3)常用事件
WebSocket.onclose
:用于指定连接关闭后的回调函数。
WebSocket.onmessage
:用于指定当从服务器接受到信息时的回调函数。
WebSocket.readyState
:链接状态
-
0 (WebSocket.CONNECTING):正在链接中
-
1 (WebSocket.OPEN):已经链接并且可以通讯
-
2 (WebSocket.CLOSING):连接正在关闭
-
3 (WebSocket.CLOSED):连接已关闭或者没有链接成功
4 使用
useEffect(() => {// 1. 创建websockets对象,参数为服务器websockets地址const websockets = new WebSocket(`wss://${window.location.host}/ws/inner/message/start`);console.log('websockets:', websockets);// 2. 监听接收消息的情况websockets.onmessage = (res) => {console.log('onmessage:', res);// 信息处理const msg = JSON.parse(res?.data);const url = msg?.id ? `${basePath}/message-center?id=${msg?.id}` : `${basePath}/message-center`;notification.info({message: 'New Message',description: (<>{msg?.title} <a onClick={() => history.push(url)}>read more</a ></>),});if (msg?.id) {// id存在的情况下,说明是新信息,当点击read more进入消息中心页面的时候,需要直接弹窗显示最新信息;否则表示刚进入页面时候的欢迎信息store.dispatch(setMessageData({ newMessageItem: msg }));}// 重新获取未读的信息数量runUnreadMessageList();};return () => {websockets.close();};}, []);
链接成功后,弹出消息提示:
websocket对象和onmessgae截图:
控制台截图: