1、前言
目前JS實時通信方式主要由:websocket、socket.io、eventSource(SSE)這三種方式。有人就也許好奇有了websocket這種實時通信方式,為啥還需要eventSource呢?這是因為不同客戶端場景,有著各自的優(yōu)勢。
eventSource是單向通信,而websocket是雙向通信。在新聞推送、股票行情這種只需要服務(wù)器發(fā)送消息給客戶端場景,使用SSE更加合適,另外SSE是使用HTTP傳輸?shù)?。而websocket要求全雙工連接和一個新的websocket服務(wù)器去處理,
因為各有所長,我們只需要根據(jù)實際應(yīng)用場景,去選擇最優(yōu)的應(yīng)用方案。
2、介紹
EventSource 對象接口用于接收服務(wù)器發(fā)送的事件。它通過 HTTP 連接到服務(wù)器,已 text/event-stream
格式接收事件,不關(guān)閉連接。
EventSource 對象主要用于 Server-Sent Events(簡稱 SSE)的技術(shù)。這是一種能讓瀏覽器通過 HTTP 連接自動收到服務(wù)器端更新的技術(shù)。
這個技術(shù)的作用是可以完成從服務(wù)器端到客戶端(瀏覽器)單向的消息傳遞。因此我們可以用這個來做推送。
相關(guān)文檔:https://developer.mozilla.org/zh-CN/docs/Web/API/EventSource
2.1瀏覽器兼容性
2.2構(gòu)造函數(shù)
const eventSource = new EventSource()
2.3屬性
說明 | 屬性 |
---|
onerror | 當發(fā)生錯誤時被調(diào)用,并且在此對象上派發(fā) error 事件 |
onmessage | 服務(wù)器端發(fā)送給客戶端一條消息時觸發(fā) |
onopen | SSE 連接剛打開時觸發(fā) |
readyState | 表示連接狀態(tài)(CONNECTING 、OPEN 和 CLOSED ) |
url | 代表源頭的 URL |
2.4方法
2.5通信過程
在瀏覽器通信截圖:
2.6服務(wù)端
服務(wù)端返回響應(yīng)頭必須包含以下header:
Content-Type: text/event-steam
Cache-Control: no-cache
Connection: keep-alive
服務(wù)器返回的數(shù)據(jù)格式為文本型,由若干個message組成,每個message用\n\n分割
每個message內(nèi)容是[key]:value
key有四種情況:id、event(type)、data、tetry
id 為每個返回數(shù)據(jù)的唯一標識,瀏覽器用lastEventId讀取id,一旦連接斷開,瀏覽器會從新發(fā)送http請求,帶有特殊請求頭Last-Event-Id,代表斷開時的id,用于建立重新連接,屬于一種重連的同步機制.
data 數(shù)據(jù)內(nèi)容一般放于data字段。
event(type):消息類型,一般默認為message,服務(wù)端可以自定義,前端用addEventListener()監(jiān)聽。
retry:代表服務(wù)器重新發(fā)送請求的間隔時間。
3、實例運用
3.1原生EventSource
/*
* new EventSource(url, configuration)
* url:請求地址路徑
* configuration 可選項:withCredentials,默認為false,指是否CORS設(shè)置
*
*/
const eventSource = new EventSource('/api/stream');
// 正常的EventSource,我們只關(guān)心以下三個事件
/*
* open:訂閱成功(和后端連接成功)
*/
eventSource.addEventListener("open", function(e) {
console.log('open successfully')
})
/*
* message:后端返回信息,格式可以和后端協(xié)商
*/
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')
})
// 需要關(guān)閉了
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 編輯過