原帖
服务端实时推送数据,除了用 WebSocket 外,还可以用 HTTP 的 <font style="color:rgb(37, 41, 51);">Server Send Event</font>
(SSE)。
只要 http 返回 Content-Type 为 text/event-stream 的 header,就可以通过 stream 的方式多次返回消息了。它传输的是 json 格式的内容,可以用来传输文本或者二进制内容。

一次请求,随后就是多次响应,简单又直接,而且连接断了,浏览器会自动重连。而 WebSocket 需要手动重连。
控制台中也能看到清晰的消息列表:

后端
nest 后端使用 <font style="color:rgb(37, 41, 51);">@Sse</font>
然后返回 Observe 对象就可以了。内部可以通过 observer.next 随时返回数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| @Sse('stream') stream() { return new Observable<{ data: { msg: string } }>((observer) => { observer.next({ data: { msg: 'aaa' } }); setTimeout(() => { observer.next({ data: { msg: 'bbb' } }); }, 2000); setTimeout(() => { observer.next({ data: { msg: 'ccc' } }); }, 4000); }); }
@Sse('stream2') stream2() { const childProcess = exec('tail -f ./log'); return new Observable((observer) => { childProcess.stdout.on('data', (m) => { observer.next({ data: { msg: m.toString() } }); }); }); }
@Sse('stream3') stream3() { return new Observable((observer) => { const json = readFileSync('./package.json').toJSON(); observer.next({ data: { msg: json }}); }); }
|
前端
前端使用 <font style="color:rgb(37, 41, 51);">EventSource</font>
的 onmessage 来接收消息。
| const eventSource = new EventSource("http://localhost:3000/stream"); eventSource.onmessage = ({ data }) => { console.log("New message", JSON.parse(data)); };
|
这个 api 的兼容性很好,除了 ie 外可以放心的用。
它的应用场景有很多,比如站内信、构建日志实时展示、chatgpt 的消息返回等。
再遇到需要消息推送的场景,不要直接 WebSocket 了,也许 Server Send Event 更合适捏