什么是JavaScript中的服務(wù)器發(fā)送事件?
在 Web 應(yīng)用程序開發(fā)中,經(jīng)常需要將服務(wù)器上的數(shù)據(jù)實時顯示在客戶端上。愛掏網(wǎng) - it200.com以往的做法是輪詢,在客戶端不斷地向服務(wù)器發(fā)送請求,服務(wù)器返回數(shù)據(jù),這樣會占用大量的帶寬和服務(wù)器資源。愛掏網(wǎng) - it200.com然而,現(xiàn)在有一個更好的解決方案——服務(wù)器發(fā)送事件(Server-Sent Events,簡稱 SSE)。愛掏網(wǎng) - it200.com
服務(wù)器發(fā)送事件(SSE)機制是一種基于HTTP協(xié)議的服務(wù)器推送技術(shù)。愛掏網(wǎng) - it200.com它允許服務(wù)器向客戶端推送任意數(shù)量的消息,從而能夠?qū)崿F(xiàn)服務(wù)器主動推送數(shù)據(jù)到客戶端的效果。愛掏網(wǎng) - it200.comSSE 常用于實時性要求較高的應(yīng)用場景,如股票交易、拍賣等,通常被認為是 WebSocket 技術(shù)的一種替代方案,使用 SSE 比使用 WebSocket 更加輕量級。愛掏網(wǎng) - it200.com
SSE 與 WebSocket 不同,SSE 采用的是單向通信的方式。愛掏網(wǎng) - it200.com當客戶端向指定的 URL 發(fā)送一個 SSE 請求時,瀏覽器會在建立連接之后一直等待直到服務(wù)器發(fā)送一條消息為止。愛掏網(wǎng) - it200.com這種方式避免了 WebSocket 的雙向通信所引發(fā)的一些安全問題,并且不需要額外的握手流程,可以快速地建立連接和傳輸數(shù)據(jù)。愛掏網(wǎng) - it200.com
使用 SSE 需要借助一個新的瀏覽器 API:EventSource,它定義了與服務(wù)器建立 SSE 連接的方法。愛掏網(wǎng) - it200.com
要建立 SSE 連接,只需要在客戶端代碼中創(chuàng)建一個 EventSource 對象,然后調(diào)用它的 open
方法,傳入一個服務(wù)器地址作為參數(shù):
const source = new EventSource('/sse')
如果服務(wù)器設(shè)置了 CORS(跨域資源共享)響應(yīng)頭,那么需要將 EventSource
構(gòu)造函數(shù)的第一個參數(shù)設(shè)置為完整的 URL 。愛掏網(wǎng) - it200.com在服務(wù)器端,需要監(jiān)聽請求的 URL,并向客戶端發(fā)送 SSE 事件。愛掏網(wǎng) - it200.com下面是一個簡單的 Node.js 例子,監(jiān)聽 /sse
路徑的 GET 請求,并且每秒鐘向客戶端推送一條消息:
const http = require('http')
const server = http.createServer((req, res) => {
if (req.url === '/sse') {
res.writeHead(200, {
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive'
})
let id = 0
setInterval(() => {
res.write(`id: {id}\n`)
res.write(`data:{new Date().toISOString()}\n\n`)
id++
}, 1000)
} else {
res.writeHead(404)
res.end()
}
})
server.listen(3000, () => {
console.log('Server is listening on http://localhost:3000')
})
上面的代碼使用了 setInterval
方法每秒鐘向客戶端推送一條消息,由于 SSE 是單向通信,因此只需要將消息以特定格式發(fā)送給客戶端即可。愛掏網(wǎng) - it200.com
在客戶端,可以監(jiān)聽 EventSource 對象的 message
事件,當服務(wù)器向客戶端發(fā)送消息時,會觸發(fā)該事件:
source.onmessage = event => {
console.log(event.data)
}
event.data
屬性包含服務(wù)器發(fā)送的數(shù)據(jù)。愛掏網(wǎng) - it200.comSSE 支持多種類型的消息,例如:普通文本、JSON、HTML 等。愛掏網(wǎng) - it200.com
當客戶端與服務(wù)器的 SSE 連接發(fā)生錯誤時,會觸發(fā) EventSource 對象的 error
事件。愛掏網(wǎng) - it200.com通過該事件的 event.target.readyState
屬性可以獲取當前連接的狀態(tài):
0
:連接已經(jīng)關(guān)閉。愛掏網(wǎng) - it200.com1
:正在連接。愛掏網(wǎng) - it200.com2
:已經(jīng)建立連接,可以接收服務(wù)器發(fā)送的數(shù)據(jù)。愛掏網(wǎng) - it200.com
與 XMLHttpRequest
對象不同,EventSource對象支持重連機制,當連接斷開時,瀏覽器會自動發(fā)起新的連接請求。愛掏網(wǎng) - it200.com可以通過 EventSource.retry
屬性來控制重連策略,例如:
const source = new EventSource('/sse')
source.retry = 3000 // 每隔 3 秒嘗試重新連接一次
SSE 的優(yōu)點
相對于輪詢、Comet 等技術(shù),SSE 有以下幾點優(yōu)點:
- 省去了客戶端不斷向服務(wù)器發(fā)送請求的過程,減少帶寬和服務(wù)器資源的損耗。愛掏網(wǎng) - it200.com
- SSE 與 WebSocket 相比,SSE 協(xié)議更加輕量級。愛掏網(wǎng) - it200.com不需要進行復(fù)雜的握手流程,可以快速建立連接和傳輸數(shù)據(jù)。愛掏網(wǎng) - it200.com
- SSE 可以支持自定義事件、重連機制、超時機制等豐富的特性。愛掏網(wǎng) - it200.com
- SSE 提供了對跨域請求的支持,可以安全地將信息發(fā)送給任何站點,而不必擔心安全問題。愛掏網(wǎng) - it200.com
SSE 的缺點
盡管 SSE 提供了一種實時推送數(shù)據(jù)的便捷方式,但是它的缺點也是存在的:
- SSE 采用的單向通信方式,只能從服務(wù)器向客戶端發(fā)送數(shù)據(jù),不支持雙向通信。愛掏網(wǎng) - it200.com
- SSE 的兼容性在一定程度上依賴于瀏覽器。愛掏網(wǎng) - it200.com雖然現(xiàn)代瀏覽器基本上都支持 SSE,但是特定的瀏覽器和版本可能不支持 SSE。愛掏網(wǎng) - it200.com
結(jié)論
SSE 是一種比較新的服務(wù)器推送技術(shù),與傳統(tǒng)的輪詢方式相比,SSE 更加高效,并且可以實現(xiàn)實時推送數(shù)據(jù)的需求。愛掏網(wǎng) - it200.com相對于 WebSocket 技術(shù)而言,SSE 的協(xié)議更加輕量級,適用于一些不需要復(fù)雜的雙向通信的應(yīng)用場景。愛掏網(wǎng) - it200.com雖然 SSE 的兼容性存在一定問題,但是該技術(shù)在開發(fā)實時應(yīng)用時還是值得考慮的。愛掏網(wǎng) - it200.com