- y-websocket:和 yjs 配套的一个通信库。
- BroadcastChannel:这个只在同一台设备,同一个浏览器有效。
实时场景的旧处理方案#
考虑网页中的以下场景:
- 股票K线图
- 聊天
- 警报、重要通知
- 余座
- 抢购页面的库存
- …
上述场景有一个共同特点——实时性
这种对实时性有要求的页面,会带来一些问题
比如下面的聊天场景
由于HTTP协议是请求-响应模式,请求必须在前,响应必须在后,这就导致了服务器无法「主动」的把消息告诉客户端。
开发者想了很多办法来解决这一问题
当然终极解决方案自然是WebSocket,但了解过去的一些做法、参观前辈们经历的痛苦还是有益的。
短轮询#
short polling,中文翻译为短轮询,是一种「话痨式」的方式。
客户端每隔一小段时间就向服务器请求一次,询问有没有新消息

实现短轮询是非常简单的,客户端只需要设置一个计时器不断发送请求即可
这种方案的缺陷是非常明显的:
- 会产生大量无意义的请求
- 会频繁打开关闭连接
- 实时性并不高
长轮询#
我们的前辈在有限的条件下,充分发挥智慧,来解决短轮询的问题,于是演化为长轮询

长轮询有效的解决了「话痨问题」,让每一次请求和响应都是有意义的
但长轮询仍然存在问题:
-
客户端长时间收不到响应会导致超时,从而主动断开和服务器的连接
这种情况是可以处理的,让ajax请求因为超时而结束时,立即重新发送请求到服务器
虽然这种做法会让之前的请求变得无意义,但毕竟比短轮询好多了
-
由于客户端可能「过早的」请求了服务器,服务器不得不挂起这个请求直到新消息的出现。这会让服务器长时间的占用资源却没什么实际的事情可做。
WebSocket#
伴随着HTML5出现的WebSocket,从协议上赋予了服务器主动推送消息的能力
从上图可以看出:
-
WebSocket也是建立在TCP协议之上的,利用的是TCP全双工通信的能力
- 单工模式:数据的流向是单向的,不能反向,类似于收音机
- 半双工:同一时候数据只能单向传输(要么是发送,要么是接收),类似于对讲机
- 全双工:同一时候可以双向传输,类似于打电话
-
使用WebSocket,会经历两个阶段:握手阶段、通信阶段
虽然优于轮询方案,但WebSocket仍然是有缺点的:
-
兼容性
WebSocket是HTML5新增的内容,因此古董版本的浏览器并不支持
-
维持TCP连接需要耗费资源
对于那些消息量少的场景,维持TCP连接确实会造成资源的浪费
原生API#
https://developer.mozilla.org/zh-CN/docs/Web/API/WebSocket/WebSocket
const ws = new WebSocket('websocket服务器地址') // 创建一个 websocket 连接
// 事件:// 握手完成后会触发ws.onopen = function () {}// 收到服务器消息的时候会触发ws.onmessage = function () {}// 连接关闭之后会触发ws.onclose = function () {}
// 方法:ws.send(消息) // 向 websocket 服务器发送消息
// 属性:ws.readyState // 连接状态 0-正在连接中 1-已连接 2-正在关闭中 3-已关闭Socket.io#
原生的接口虽然简单,但是在实际应用中会造成很多麻烦
比如一个页面,既有K线,也有实时聊天,于是:
上图是一段时间中服务器给客户端推送的数据,你能区分这些数据都是什么意思吗?
这就是问题所在:连接双方可以在任何时候发送任何类型的数据,另一方必须要清楚这个数据的含义是什么
回忆HTTP是如何处理这个问题的
你会如何解决这个问题
虽然我们可以自行解决这些问题,但毕竟麻烦
Socket.io 帮助我们解决了这些问题,它把消息放到不同的事件中,通过监听和触发事件来实现对不同消息的处理
客户端和服务器双方事先约定好不同的事件(这些事件全部都是自定义事件),事件由谁监听,由谁触发,就可以把各种消息进行有序管理了。
-EOF-