EventSource
当不使用 HTTP/2 时, 服务器发送事件(SSE)受到打开连接数(6)的限制, 这个限制是针对浏览器的. 每个浏览器的所有标签页中对相同域名的连接数最多支持 6 个(chrome 超过 6 个自动断开连接, firefox 超过 9 个自动断开连接)
当使用 HTTP/2 时, 最大并发 HTTP 流的数量是由服务器和客户端协商的(默认为 100)
Web 内容与服务器发送事件通信的接口, 通信方向是单向的, 数据消息只能从服务器发送到客户端. 如果接收消息中有一个 event 字段, 触发的事件与 event 字段的值相同, 如果不存在 event 字段, 则将触发通用的 message 事件
- url, 表示远程资源的位置
- configuration, 可选, 一个对象
- withCredentials, 标识 CORS 是否包含凭据, 默认为 false
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| const sse = new EventSource(url, configuration);
sse.onmessage = function (e) { console.log(e); };
sse.addEventListener('notice', (e) => { console.log(evt); });
|
实例属性
- readyState, 标识连接状态的数字
- CONNECTING(0)
- OPEN(1)
- CLOSED(2)
- url, 表示远程资源的位置的字符串
- withCredentials, 标识是否使用跨域资源共享(CORS)凭据来实例化
实例方法
- close(), 关闭链接, 并将 readyState 属性设置为 CLOSED
事件
- error, 连接失败时触发
- message, 接收到数据时触发
- open, 连接打开时触发
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
| <p><button id="close">Close</button></p> <ul id="list"></ul> <script> const sse = new EventSource('/evt-source', { withCredentials: true }); const list = document.getElementById('list'); const liMessageColor = 'rgb(' + Math.floor(Math.random() * 256) + ',' + Math.floor(Math.random() * 256) + ',' + Math.floor(Math.random() * 256) + ')' const liNoticeColor = 'rgb(' + Math.floor(Math.random() * 256) + ',' + Math.floor(Math.random() * 256) + ',' + Math.floor(Math.random() * 256) + ')' const btn = document.getElementById('close')
btn.onclick = function () { sse.close() }
sse.addEventListener('connected', function (e) { console.log('connected', e) })
sse.addEventListener('notice', function (e) { console.log('notice', e) const data = JSON.parse(e.data) const li = document.createElement('li') li.style.color = liNoticeColor li.innerHTML = 'event: ' + e.type + ' count:' + data.count list.appendChild(li) })
sse.addEventListener('message', function (e) { console.log('message', e) const data = JSON.parse(e.data) const li = document.createElement('li') li.style.color = liMessageColor li.innerHTML = 'event: ' + e.type + ' count:' + data.count list.appendChild(li) })
sse.addEventListener('closed', function (e) { console.log('closed', e) })
sse.addEventListener('open', function (e) { console.log('open', e) })
sse.addEventListener('error', function (e) { console.log('error', e) }) </script>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| import express from 'express';
const app = express() let count = 1
app.use(express.static('./'))
app.get('/evt-source', (req, res) => { res.setHeader('Content-Type', 'text/event-stream'); res.setHeader('Cache-Control', 'no-cache'); res.setHeader('Connection', 'keep-alive');
const sendEvent = (evtName, data) => {
res.write(`event: ${evtName}\nid: ${Date.now()}\nretiry: 10\ndata: ${JSON.stringify(data)}\n\n`); };
sendEvent('connected', { message: 'Connection established' });
const timer = setInterval(() => { sendEvent(Math.random() > 0.5 ? 'notice' : 'message', { message: `Message at ${new Date().toISOString()}`, count: count }); count++; }, 5000);
req.on('close', () => { clearInterval(timer); res.end() }); })
app.get('/eventSource.html', (req, res) => { res.sendFile('./eventSource.html') })
app.listen(8080, () => { console.log('app listen localhost:8080') })
|