Bootstrap

服务器推送数据之SSE (server send event)

SSE

  • 一个客户端获取新的数据通常需要发送一个请求到服务器,也就是向服务器请求的数据。
  • SSE(Server Send Event)服务器推送。使用 server-sent 事件,服务器可以在任何时刻向我们的客户端推送数据和信息。这些被推送进来的信息可以在这个客户端上作为 Events + data 的形式来处理。
  • https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events

基本应用

  • 服务端设置
    • 设置头部
      "Content-type","text/event-stream"
    • 返还数据格式
      • data:声明数据开始
      • \r\n\r\n标志数据结尾
ctx.body = `
	event: ping\n
	data: {"time": "${new Date()}"}
	\n\n
`
  • 前端获取使用EventSource 类
let source = new EventSource("/test");
source.onopen = function(){
      console.log("连接建立...",this.readyState);
}
// console.log(source)
source.onmessage = function(evnet){
    console.log("数据是:",evnet.data)
}
source.error = function(err){
    return console.log('err');
}
  • readyState 代表连接状态:
    • 0: CONNECTING
    • 1: OPEN
    • 2: CLOSED

demo

  • app.js
const http = require('http');
const fs = require('fs');
let str = "[]";
const app = http.createServer((req, res) => {
    if (req.url === '/index.html') {
        let content = fs.readFileSync('./index.html');
        res.setHeader('content-type', 'text/html;charset=utf-8');
        res.end(content);
        return;
    }
    if (req.url === '/getData') {
        getData(res);
    }
});
async function getData(res) {
    res.setHeader('content-type', 'text/event-stream');
    for (let i= 0; i<10; i++) {
        await new Promise(resolve => {
            setTimeout(() => {
                resolve();
            }, 1000)
        });
        res.write(`event: abc\ndata: {"time": "${new Date()}"}\n\n`);
    }
    res.end();
}
app.listen(8081);
  • index.html
<!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>
    <h1>EventSource</h1>
    <div id="box"></div>
    <script>
        let box = document.querySelector('#box')
        let source = new EventSource("/getData");
        source.addEventListener('open', function() {
            console.log('开启了');
        })
        source.addEventListener('abc', e => {
            console.log('e', e);
            let data = JSON.parse(e.data);
            box.innerHTML += `<p>${data.time}</p>`;
        })
    </script>
</body>
</html>
;