一个超级好用,但又有点冷门的信息推送Server Send Event(SSE)

应用场景

在目前项目中,经常有好多交互信息需要事实的更新,在当前项目中有智能硬件,服务器,客户端三者之间的通信。

经常一个http请求的交互到服务端,服务端与硬件进行一次交互,收到通知再告知客户端。一个交互链路的变长,发生错误的概率就会大大的增加,万一某一个环节出了问题,都会导致整个通信全部失败。率先整个简单粗暴的websocket服务再说。后面觉得websocket有点low,物联网那块很多都用mq,领导已决定,那就换成mqtt吧,mqtt的实践可以查看之前发布的文章。后面在uniapp打包成apk后,兼容性太差,不能用了,换成3,4版本都存在问题,后面只能打包成h5.再嵌套android壳。有点不甘心,在广泛阅读文档中发现SSE即(Server Send Event)也是个不错的选择。

Server Send Event(SSE)概念

Server Send Event (SSE)是HTML5的API,用于在服务器和客户端之间实时推送数据流。它与WebSocket不同的是,SSE是一个单工通信,是服务端向客户端定向的推送消息。

Server Send Event协议

SSE协议本质上就是一个Http的get请求,当然也是支持Https,服务端在接到该请求后,返回状态。同时请求头设置也变为流形式。

yaml 复制代码
 Content-Type: text/event-stream,
 Cache-Control: no-cache,
 Connection: keep-alive

兼容性

客户端实现

客户端通过EventSource对象与服务器的一个http get请求建立长连接。

new EventSource()建立与服务端的连接。

onmessage()用来监听服务端发来的消息。

onerror()用来监听连接的错误。

客户端代码如下。

xml 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
 <h2>Server Send Event测试</h2>
 <ul id="ul">
 
 </ul>
<script>
    const source = new EventSource('/sse');
    source.onopen = () => {
        console.log('连接成功');
    }
    source.onmessage = (res) => {
        console.log('获得的数据是:' + res.data );
        var ulDoom = document.getElementById('ul')
        var child = document.createElement('li')
        child.innerHTML=res.data
        ulDoom.append(child)
    }
    source.onerror = (err) => {
        console.log(err);
    }
</script>

  
</body>
</html>

服务端实现

PassThrough将字节转成流形式。

router.get('/sse', async (ctx, next),创建一个get请求(也就是路由,用来响应)。

Content-Type': 'text/event-stream 这里必须将请求设置成流的形式 ctx.body = stream;将消息以流的形式返回给客户端

javascript 复制代码
const Koa = require('koa');
const Router = require('koa-router');
const { PassThrough } = require('stream')

//路径管理
const path = require('path');

const static = require('koa-static');
const main = static(path.join(__dirname) + '/www/');

const app = new Koa();
const router = new Router();

app.use(main)

// 发送消息
const sendMessage = async (stream) => {
  const data = [
    'hello,jerry',
    'have not see you for a long time',
    'how are you',
    'what are you doing now ',
    'i am missing you',
  ];

  // 循环上面数组: 推送数据、休眠 2 秒
  for (const value of data) {
    stream.write(`data: ${JSON.stringify(value)}\n\n`); // 写入数据(推送数据)
    await new Promise((resolve) => setTimeout(resolve, 2000));
  }

  // 结束流
  // stream.end();
};


// SSE 路由处理
router.get('/sse', async (ctx, next) => {
     // 设置响应头
     ctx.set({
      'Content-Type': 'text/event-stream',
      'Cache-Control': 'no-cache',
      'Connection': 'keep-alive'
  });

 // 2. 创建流、并作为接口数据进行返回
 const stream = new PassThrough();
 ctx.body = stream;
 ctx.status = 200;

 // 3. 推送流数据
 sendMessage(stream, ctx);
});

app.use(router.routes()).use(router.allowedMethods());

app.listen(3000, () => {
    console.log('Server is running on http://localhost:3000');
});

运行成功截图

相关推荐
m0_748252235 分钟前
Python 入门教程(2)搭建环境 2.4、VSCode配置Node.js运行环境
vscode·python·node.js
青红光硫化黑8 分钟前
React基础之useEffect
javascript·react.js·ecmascript
bin915315 分钟前
DeepSeek 助力 Vue3 开发:打造丝滑的表格(Table)之添加列宽调整功能,示例Table14基础固定表头示例
前端·javascript·vue.js·ecmascript·deepseek
二川bro22 分钟前
TensorFlow.js 全面解析:在浏览器中构建机器学习应用
javascript·机器学习·tensorflow
颜酱23 分钟前
后台系统从零搭建(三)—— 具体页面之部门管理(抽离通用的增删改查逻辑)
前端·javascript·react.js
qq_3325394523 分钟前
JavaScript性能优化实战指南
前端·javascript·性能优化
wkj00137 分钟前
Vue 项目中,.env文件怎么用?
前端·javascript·vue.js
星之卡比*37 分钟前
前端0基础---day18Math - Date - 定时器 (javascript)
开发语言·前端·javascript
HackerTom38 分钟前
html播放本地音乐
前端·javascript·html·音乐·audio
星辰tsy42 分钟前
JS内存泄漏问题
开发语言·javascript