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}
data: ${JSON.stringify(data)}

`)
}


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} data: ${JSON.stringify(data)} `) } 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); }
原文地址:https://www.cnblogs.com/naturl/p/15049186.html