event-source-polyfill库中如何监听其他事件
服务端在使用 EventSource
推送自定义事件类型时,主要通过响应体来指定事件类型,而不是在 HTTP 头字段中。
具体实现步骤如下:
设置内容类型:首先,服务端要返回Content-Type: text/event-stream
,表明这是一个事件流。构造响应体:在响应体中,使用 event:
字段来指定事件类型。客户端可以用这个事件类型通过 addEventListener
监听。 具体格式
服务端发送的每一条消息都按如下格式构造:
event: <event-name> data: <event-data>
其中:
event:
后面的内容是事件类型,比如 update
,如果不指定这个字段,默认事件类型就是 message
。data:
是事件的具体内容,可以是 JSON、文本等。 代码示例(Node.js + Express)
以下是一个简单的示例,展示如何在服务端配置自定义事件类型:
const express = require('express');const app = express();app.get('/events', (req, res) => { res.setHeader('Content-Type', 'text/event-stream'); res.setHeader('Cache-Control', 'no-cache'); res.setHeader('Connection', 'keep-alive'); res.status(200); res.flushHeaders();// 及时发送刷新响应头 // 定时发送自定义update事件 setInterval(() => { res.write('event: update\n'); res.write('data: {"message": "This is an update event"}\n\n'); }, 3000); // 发送默认 message 事件 setInterval(() => { res.write('event: message\n');//默认事件类型,可不写 res.write('data: {"message": "This is a message event"}\n\n'); }, 5000);});app.listen(3000, () => { console.log('Server is running on http://localhost:3000');});
客户端监听
对于上述服务端代码,客户端可以像这样监听 update
和默认的 message
事件:
原生写法:
const eventSource = new EventSource('http://localhost:3000/events');// 监听 'update' 事件eventSource.addEventListener('update', (event) => { console.log('Update event:', event.data);});// 监听默认的 'message' 事件eventSource.onmessage = (event) => { console.log('Message event:', event.data);};
event-source-polyfill库写法:
import { EventSourcePolyfill } from 'event-source-polyfill';const eventSource = new EventSourcePolyfill('http://localhost:3000/events');eventSource.onopen = (event) =>{ console.log("连接成功", event); };// 监听自定义事件 'update'eventSource.addEventListener('update', (event) => { console.log('Update event:', event.data);});// 监听默认的 'message' 事件eventSource.onmessage = (event) => { console.log('Message event:', event.data);};// 监听错误事件eventSource.onerror = (error) => { console.error('EventSource encountered an error:', error);};
使用 EventSourcePolyfill
时,其 API
和标准EventSource
完全兼容。
注意
事件流结构:每个事件之间要用两个换行符\n\n
隔开,表示事件结束。保持连接:EventSource
是长连接,服务端需避免连接超时,可能需要定期发送心跳包。 定期发送心跳包
EventSourcePolyfill
支持自定义重连时间间隔,可以通过 heartbeatTimeout
配置选项来设置。
使用示例
以下示例展示了如何使用 EventSourcePolyfill
的 heartbeatTimeout
参数来设置重连间隔:
import { EventSourcePolyfill } from 'event-source-polyfill';// 设置重连时间间隔(单位为毫秒)const eventSource = new EventSourcePolyfill('http://localhost:3000/events', { heartbeatTimeout: 10000 ,// 10秒 headers: { Authorization:token?token:"Bearer niuniu", } });// 监听事件eventSource.onmessage = (event) => { console.log('Message event:', event.data);};
参数解释
heartbeatTimeout
:表示连接失活前等待的最大时间间隔(单位是毫秒)。如果在该时间内没有收到服务端的数据,EventSourcePolyfill
会尝试重新连接。这在服务器没有主动发送心跳数据的情况下尤其有用。 服务端的心跳配置
通常,为了保持连接状态,服务端也可以每隔一段时间发送一个空的数据包作为心跳,例如:
// 服务端心跳实现示例setInterval(() => { res.write(':\n\n'); // ":" 是注释行,不会被客户端处理,但保持连接活跃}, 10000); // 10秒
这样可以减少客户端的自动重连频率,优化网络资源。
什么是res.flushHeaders()
res.flushHeaders()
是 Express(基于 Node.js 的 HTTP 响应对象)的一个方法,作用是在不发送响应主体的情况下立即将响应头发送给客户端。这在处理流式响应(如 Server-Sent Events 或文件流下载)时特别有用。
用法和作用
通常,Express 在发送响应主体之前会自动发送响应头,但有时我们希望在发送内容之前就发送响应头信息。res.flushHeaders()
就是为这种情况设计的:
使用示例
在实现 SSE 时,通常会用到 res.flushHeaders()
以保证头信息在内容流发送之前发送:
app.get('/events', (req, res) => { // 设置响应头 res.setHeader('Content-Type', 'text/event-stream'); res.setHeader('Cache-Control', 'no-cache'); res.setHeader('Connection', 'keep-alive'); // 强制立即发送响应头 res.flushHeaders(); // 发送数据流 setInterval(() => { res.write(`data: ${JSON.stringify({ message: "Hello, SSE!" })}\n\n`); }, 3000);});
注意事项
兼容性:res.flushHeaders()
仅在支持 flushHeaders
的 Node.js 版本中可用(Node.js v8.13+)。流式响应:该方法适用于长连接或流式内容传输的场景,不适合用于短连接请求。