当前位置:首页 » 《我的小黑屋》 » 正文

前端SSE包event-source-polyfill的其他事件监听的实现

2 人参与  2024年12月04日 08:01  分类 : 《我的小黑屋》  评论

点击全文阅读


event-source-polyfill库中如何监听其他事件

服务端在使用 EventSource 推送自定义事件类型时,主要通过响应体来指定事件类型,而不是在 HTTP 头字段中。

具体实现步骤如下:

设置内容类型:首先,服务端要返回 Content-Type: text/event-stream,表明这是一个事件流。构造响应体:在响应体中,使用 event: 字段来指定事件类型。客户端可以用这个事件类型通过 addEventListener 监听。

具体格式

服务端发送的每一条消息都按如下格式构造:

event: <event-name>  data: <event-data>  

其中:

event: 后面的内容是事件类型,比如 update,如果不指定这个字段,默认事件类型就是 messagedata: 是事件的具体内容,可以是 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 配置选项来设置。

使用示例

以下示例展示了如何使用 EventSourcePolyfillheartbeatTimeout 参数来设置重连间隔:

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(服务器推送事件)或实时数据传输的场景中,发送响应头后保持连接,可以在不关闭连接的情况下持续传输数据。

使用示例

在实现 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+)。流式响应:该方法适用于长连接或流式内容传输的场景,不适合用于短连接请求。

典型应用场景

SSE(Server-Sent Events):立即发送头信息保持连接,然后持续推送数据。文件下载:在文件分块下载时预先发送响应头,后续分块传输数据。

点击全文阅读


本文链接:http://zhangshiyu.com/post/196284.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1