1、前言
目前JS实时通信方式主要由:websocket、socket.io、eventSource(SSE)这三种方式。有人就也许好奇有了websocket这种实时通信方式,为啥还需要eventSource呢?这是因为不同客户端场景,有着各自的优势。
eventSource是单向通信,而websocket是双向通信。在新闻推送、股票行情这种只需要服务器发送消息给客户端场景,使用SSE更加合适,另外SSE是使用HTTP传输的。而websocket要求全双工连接和一个新的websocket服务器去处理,
因为各有所长,我们只需要根据实际应用场景,去选择最优的应用方案。
2、介绍
EventSource 对象接口用于接收服务器发送的事件。它通过 HTTP 连接到服务器,已 text/event-stream
格式接收事件,不关闭连接。
EventSource 对象主要用于 Server-Sent Events(简称 SSE)的技术。这是一种能让浏览器通过 HTTP 连接自动收到服务器端更新的技术。
这个技术的作用是可以完成从服务器端到客户端(浏览器)单向的消息传递。因此我们可以用这个来做推送。
相关文档:https://developer.mozilla.org/zh-CN/docs/Web/API/EventSource
2.1浏览器兼容性
2.2构造函数
const eventSource = new EventSource()
2.3属性
说明 | 属性 |
---|
onerror | 当发生错误时被调用,并且在此对象上派发 error 事件 |
onmessage | 服务器端发送给客户端一条消息时触发 |
onopen | SSE 连接刚打开时触发 |
readyState | 表示连接状态(CONNECTING 、OPEN 和 CLOSED ) |
url | 代表源头的 URL |
2.4方法
2.5通信过程
在浏览器通信截图:
2.6服务端
服务端返回响应头必须包含以下header:
Content-Type: text/event-steam
Cache-Control: no-cache
Connection: keep-alive
服务器返回的数据格式为文本型,由若干个message组成,每个message用\n\n分割
每个message内容是[key]:value
key有四种情况:id、event(type)、data、tetry
3、实例运用
3.1原生EventSource
/*
* new EventSource(url, configuration)
* url:请求地址路径
* configuration 可选项:withCredentials,默认为false,指是否CORS设置
*
*/
const eventSource = new EventSource('/api/stream');
// 正常的EventSource,我们只关心以下三个事件
/*
* open:订阅成功(和后端连接成功)
*/
eventSource.addEventListener("open", function(e) {
console.log('open successfully')
})
/*
* message:后端返回信息,格式可以和后端协商
*/
eventSource.addEventListener("message", function(e) {
console.log(e.data)
})
/*
* error:错误(可能是断开,可能是后端返回的信息)
*/
eventSource.addEventListener("error", function(err) {
console.log(err)
// 类似的返回信息验证,这里是实例
err && err.status === 401 && console.log('not authorized')
})
// 需要关闭了
eventSource.close()
注意:因为原生EventSource无法进行自定义配置,例如header、method等,因此我们需要引用其他的封装库
3.2fetch-event-source
使用post的方式请求eventSource
安装依赖:npm install --save @rangermauve/fetch-event-source
import { fetchEventSource } from '@microsoft/fetch-event-source'
fetchEventSource('/api/stream', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(dataJson),
onopen() {},
onmessage(event) {
const jsonData = JSON.parse(event.data)
let respondTexts = jsonData.delta
let finishStatus = jsonData.finished
},
onerror() {},
onclose() {}
})
该文章在 2024/6/15 11:03:32 编辑过