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 編輯過