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); }

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章