Page 259 - Web性能权威指南
P. 259
段中提取有效载荷,检查可选的 ID 和类型,最后再分派一个 DOM 事件告知应用。
如果存在某个类型,那么就会触发自定义的 DOM 事件处理程序;否则,就会调用
通用的 onmessage 回调,参见 16.1 节“EventSource API”。
SSE 中的 UTF-8 编码与二进制传输
EventSource 不会对实际载荷进行任何额外处理:从一或多个 data 字段中提取出
来的消息,会被拼接起来直接交给应用。因此,服务器可以推送任何文本格式
(例如,简单字符串、JSON,等等),应用必须自己解码。
话虽如此,但所有事件源数据都是 UTF-8 编码的:SSE 不是为传输二进制载荷而
设计的!如果有必要,可以把二进制对象编码为 base64 形式,然后再使用 SSE。
但这样会导致很高(33%)的字节开销,参见 11.7 节“嵌入资源”。
担心 UTF-8 编码也会造成高开销? SSE 连接本质上是 HTTP 流式响应,因此响
应是可以压缩的(如 gzip 压缩),就跟压缩其他 HTTP 响应一样,而且是动态压
缩!虽然 SSE 不是为传输二进制数据而设计的,但它却是一个高效的机制——只
要让你的服务器对 SSE 流应用 gzip 压缩。
不支持二进制传输是有意为之的。SSE 的设计目标是简单、高效,作为一种服务
器向客户端传送文本数据的机制。如果你想传输二进制数据,WebSocket 才是更
合适的选择。
最后,除了自动解析事件数据,SSE 还内置支持断线重连,以及恢复客户端因断线
而丢失的消息。默认情况下,如果连接中断,浏览器会自动重新连接。SSE 规范建
议的间隔时间是 2~3 s,这也是大多数浏览器采用的默认值。不过,服务器也可以
设置一个自定义的间隔时间,只要在推送任何消息时向客户端发送一个 retry 命令
即可。
类似地,服务器还可以给每条消息关联任意 ID 字符串。浏览器会自动记录最后一
次收到的消息 ID,并在发送重连请求时自动在 HTTP 首部追加“Last-Event-ID”
值。下面看一个例子:
(既有 SSE 连接)
retry: 4500 ➊
id: 43 ➋
data: Lorem ipsum
(连接断开)
(4500 ms 后)
=> 请求
服务器发送事件 | 247