node + vue 实现服务端单向推送消息,利用EventSource

场景:后台系统需要实时收到电池报警消息,并语音提醒,前台不需要发送任何东西,所以想的是,服务端单向推送

1. 实现EventSource参考博客:

https://www.jqhtml.com/41272.html    

https://developer.mozilla.org/zh-CN/docs/Web/API/Server-sent_events/Using_server-sent_events

2. 利用events监听触发事件,主动推送消息

 

前端代码

复制代码
<script type="text/javascript">
    if(typeof(EventSource)!=="undefined"){
    let source=new EventSource("http://192.168.254.244:3001/api/messageNotic");
     source.addEventListener('test',function(e){
            console.log(e)
        });
    source.onmessage=function(event)
    {
        console.log(event)
        document.getElementById("result").innerHTML+=event.data + "<br>";
    };
}else{
    document.getElementById("result").innerHTML="抱歉,你的浏览器不支持 server-sent 事件...";
}
</script>
复制代码

 

后端代码

复制代码
// 可读流
const Readable = require('stream').Readable;

function RR() {
    Readable.call(this, arguments);
}
RR.prototype = new Readable();
RR.prototype._read = function (data) { }

const sse = (stream, event, data) => {
    return stream.push(`event:${event}\ndata: ${JSON.stringify(data)}\n\n`)
}


exports.messageNotic = async (ctx, next) => {

    let stream = new RR()
    ctx.set({
        'Content-Type': 'text/event-stream',
        'Cache-Control': 'no-cache',
        Connection: 'keep-alive'
    });
    // sse(stream, 'test', { remindFlag: new Date() });
    ctx.body = stream;

    // 每过30秒,发送一条注释语,保持和web端的连接。
    interval = setInterval(function () {
        sse(stream, 'test', { remindFlag: new Date() });
    }, 1000 * 30);

    // 监听当web端关闭eventSource, 清除定时器
    ctx.req.connection.addListener("close", function () {
        clearInterval(interval);
    }, false);

}
复制代码

 

到了这步,其实可以完成推送了,

但是如果想在产生报警日志的时候,发送提醒消息,就需要继续操作,

借用events依赖,当监听到某个事件的触发,就主动推送一条消息,

改造之后的代码如下:

复制代码

  // events事件
  const events = require('events');
  const eventEmitter = new events.EventEmitter();

//
增加一个监听事件 // 当监听到abnormalHandler 异常函数触发,往前端推送带有报警得消息 async function abnormalHandler() { eventEmitter.emit("abnormalHandler"); } function RR() { Readable.call(this, arguments); } RR.prototype = new Readable(); RR.prototype._read = function (data) { } const sse = (stream, event, data) => { return stream.push(`event:${event}\ndata: ${JSON.stringify(data)}\n\n`) } exports.messageNotic = async (ctx, next) => {
  当监听到abnormalHandler事件触发,就主动推送一条消息 eventEmitter.on(
"abnormalHandler", function () { console.log("data_receive ---> connection"); sse(stream, 'test', { remindFlag: 1 }); }); var stream = new RR() ctx.set({ 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache', Connection: 'keep-alive' }); // sse(stream, 'test', { remindFlag: new Date() }); ctx.body = stream; // 每过30秒,发送一条注释语,保持和web端的连接。 interval = setInterval(function () { sse(stream, 'test', { remindFlag: new Date() }); }, 1000 * 30); // 监听当web端关闭eventSource, 清除定时器 ctx.req.connection.addListener("close", function () { clearInterval(interval); }, false); }
复制代码

 

posted @   时光凉忆  阅读(1758)  评论(0编辑  收藏  举报
编辑推荐:
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· .NET Core 托管堆内存泄露/CPU异常的常见思路
· PostgreSQL 和 SQL Server 在统计信息维护中的关键差异
阅读排行:
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库
· 上周热点回顾(2.17-2.23)
点击右上角即可分享
微信分享提示