在项目中或多或少有一些场景会使用到长链接,除去一些聊天的项目(双向数据交换)外,更多见的如:排行榜定时刷新,大屏数据动态刷新等,往往我们只是从服务器来获取数据进行展示即可,原来除了使用定时器来发送请求获取数据外还能想到的就是WebSocket了,因为WebSocket从0集成的成本相对较大,还需要处理一些状态,所以了解到了EventSource类。仅支持从服务器发送文本数据到客户端,用的也是常规的HTTP协议,最最关键是简单。
EventSource 是服务器推送的一个网络事件接口。一个EventSource实例会对HTTP服务开启一个持久化的连接,以text/event-stream 格式发送事件, 会一直保持开启直到被要求关闭。(摘自MDN)
Server-Sent Events 规范描述了一个内建的类 EventSource,它能保持与服务器的连接,并允许从中接收事件。与 WebSocket 类似,其连接是持久的。
EventSource介绍:
补充:
客户端代码:
封装EventSourceClient:
export default class EventSourceClient { constructor(url) { this.url = url; this.eventSource = null; } // 建立连接 connection(openCallback, messageCallback, errorCallback) { this.eventSource = new EventSource(this.url); this.eventSource.onopen = openCallback; this.eventSource.onmessage = messageCallback; this.eventSource.onerror = function (e) { if (this.readyState == EventSource.CONNECTING) { console.log(`Reconnecting (readyState=${this.readyState})...`); } else { errorCallback && errorCallback(e) } }; } // 断开连接 disconnect() { this.eventSource && this.eventSource.close(); } addAction(action, fn) { this.eventSource && this.eventSource.addEventListener(action, fn); } }
使用EventSourceClient:
<script type="module"> import EventSourceClient from './event-source-client.js' const url = 'http://localhost:8080/digits' window.esc = new EventSourceClient(url); </script> <script> function start() { window.esc.connection((e) => { console.log('建立连接', e); }, (e) => { console.log('接收数据', e.data); }, (e) => { console.log('发生错误', e); }) window.esc.addAction('bye', (e) => { console.log('自定义动作', e.data); }) } function stop() { window.esc.disconnect(); console.log('关闭连接'); } </script>
服务端代码:
let http = require('http'); function onDigits(req, res) { // 设置请求头 res.writeHead(200, { 'Cache-Control': 'no-cache', // 支持跨域请求 "Access-Control-Allow-Origin": "*", // 返回类型为text/event-stream 'Content-Type': 'text/event-stream; charset=utf-8', }); let i = 0; let timer = setInterval(write, 1000); write(); function write() { i++; if (i == 4) { res.write('event: bye\ndata: bye-bye\n\n'); clearInterval(timer); res.end(); return; } res.write('data: ' + i + '\n\n'); } } function accept(req, res) { if (req.url == '/digits') { onDigits(req, res); } } http.createServer(accept).listen(8080);
执行演示:
我是小鑫同学:
- 😇熟悉:安卓开发,前端开发。
- 🤪了解:后端开发,脚本开发。
- 🧐特长:解决编码中的疑难杂症。
- 😇座右铭:积跬步以至千里,积小流以成江海。