菜单 学习猿地 - LMONKEY

VIP

开通学习猿地VIP

尊享10项VIP特权 持续新增

知识通关挑战

打卡带练!告别无效练习

接私单赚外块

VIP优先接,累计金额超百万

学习猿地私房课免费学

大厂实战课仅对VIP开放

你的一对一导师

每月可免费咨询大牛30次

领取更多软件工程师实用特权

入驻
22
0

后端数据推送-EventSource

原创
05/13 14:22
阅读数 99778

服务器发送事件(以下简称SSE)是HTML 5规范的一个组成部分,可以实现服务器到客户端的单向数据通信。通过SSE,客户端可以自动获取数据更新,而不用重复发送HTTP请求。一旦连接建立,“事件”便会自动被推送到客户端。服务器端SSE通过“事件流(Event Stream)”的格式产生并推送事件。事件流对应的MIME类型为“text/event-stream”,包含四个字段:event、data、id和retry。event表示事件类型,data表示消息内容,id用于设置客户端EventSource对象的“last event ID string”内部属性,retry指定了重新连接的时间。

node代码示例:

前端部分

var evtSource = new EventSource("http://localhost:3000");
let eventList = document.getElementsByTagName('body')[0]
// evtSource.onmessage = function(e) {
//     console.log(1111,e);
//     var newElement = document.createElement("li");
//     const eventList = document.getElementsByTagName('body')[0]
//     // console.log(eventList);
//     newElement.innerHTML = "message: " + e.data;
//     eventList.appendChild(newElement);
// }

evtSource.addEventListener("ping", function(e) {
    console.log(2222,e);    
    var newElement = document.createElement("li");
    let eventList = document.getElementsByTagName('body')[0]
    var obj = JSON.parse(e.data);
    newElement.innerHTML = "ping at " + obj.date;
    eventList.appendChild(newElement);
    
}, false);
  
evtSource.addEventListener("error",function(e){
    console.log("服务器发送给客户端的数据为:" + e.data);
});

//只要和服务器连接,就会触发open事件
evtSource.addEventListener("open",function(){
    console.log("和服务器建立连接");
 });

 //处理服务器响应报文中的load事件
 evtSource.addEventListener("load",function(e){
     console.log("服务器发送给客户端的数据为:" + e.data);
 });

  服务端部分

const http = require('http')

http.createServer((req, res) => {
    res.writeHead(200, {
        'Content-Type' : 'text/event-stream',
        'Access-Control-Allow-Origin':'*'
    })
    let i = 0;
    const timer = setInterval(()=>{
        const date = {date:new Date()}
        var content = 'event: ping\n'+"data:"+JSON.stringify(date)+"" + "\n\n";
        res.write(content);
    },1000)

    res.connection.on("close", function(){
        res.end();
        clearInterval(timer);
        console.log("Client closed connection. Aborting.");
        });

}).listen(3000)
console.log('server is run http://localhost:3000');

  java的示例

protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        //媒体类型为 text/event-stream
        response.setContentType("text/event-stream");
        response.setCharacterEncoding("utf-8");
        PrintWriter out = response.getWriter();

        //响应报文格式为:
        //data:Hello World
        //event:load
        //id:140312
        //换行符(/r/n)

        out.println("data:Hello World");
        out.println("event:load");
        out.println("id:140312");
        out.println();
        out.flush();
        out.close();
}

  SSE相较于轮询具有较好的实时性,使用方法也非常简便。然而SSE只支持服务器到客户端单向的事件推送,而且所有版本的IE(包括到目前为止的Microsoft Edge)都不支持SSE。如果需要强行支持IE和部分移动端浏览器,可以尝试EventSource Polyfill(本质上仍然是轮询)

 

参考文章:

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

 

发表评论

0/200
22 点赞
0 评论
收藏