SSE: Server-Sent Events
· 4 min read

Key Points
newEventSource(url)
的url
可以与当前网址同域,也可以跨域。跨域时,可以指定第二个参数,打开withCredentials
属性,表示是否一起发送 Cookie。EventSource
实例的readyState
属性,表明连接的当前状态。该属性只读,可以取以下值。- 0:相当于常量
EventSource.CONNECTING
,表示连接还未建立,或者断线正在重连。 - 1:相当于常量
EventSource.OPEN
,表示连接已经建立,可以接受数据。 - 2:相当于常量
EventSource.CLOSED
,表示连接已断,且不会重连。
- 0:相当于常量
source.onopen=function(event){...}
另一种写法source.addEventListener('open',function(event){...},false)
。- 如果数据很长,可以分成多行,最后一行用
\n\n
结尾,前面行都用\n
结尾。 - 浏览器用
lastEventId
属性读取这个值。一旦连接断线,浏览器会发送一个 HTTP 头,里面包含一个特殊的Last-Event-ID
头信息,将这个值发送回来,用来帮助服务器端重建连接。因此,这个头信息可以被视为一种同步机制。 - 两种情况会导致浏览器重新发起连接:一种是时间间隔到期,二是由于网络错误等原因,导致连接出错
- SSE 要求服务器与浏览器保持连接。对于不同的服务器软件来说,所消耗的资源是不一样的。Apache 服务器,每个连接就是一个线程,如果要维持大量连接,势必要消耗大量资源。Node 则是所有连接都使用同一个线程,因此消耗的资源会小得多,但是这要求每个连接不能包含很耗时的操作,比如磁盘的 IO 读写。
法二:getReader + TextDecoder + 递归读取
你可以通过 axios/fetch 获取响应流,然后手动处理流式数据。这需要结合 ReadableStream 和 TextDecoder 等 Web Streams API。
axios({
method: 'get',
url: 'https://example.com/stream',
responseType: 'stream', // 设置响应类型为流
}).then(response => {
const reader = response.data.getReader(); // 获取流的读取器
const decoder = new TextDecoder('utf-8'); // 创建解码器
reader.read().then(function processText({ done, value }) {
if (done) {
console.log('Stream complete');
return;
}
// 解码并处理数据
const chunk = decoder.decode(value, { stream: true });
console.log('Received chunk:', chunk);
// 继续读取下一个数据块
return reader.read().then(processText);
});
});