HTML5 SSE 瀏覽器發(fā)送事件
在遠(yuǎn)古時(shí)代,網(wǎng)頁大都是靜態(tài)展示,服務(wù)器無需處理復(fù)雜且過多的請(qǐng)求,只需要靜靜地等待客戶端的請(qǐng)求,將 HTML 代碼通過 HTTP 的方式返回給客戶端。因此服務(wù)器也沒有主動(dòng)推送數(shù)據(jù)給客戶端的能力,畢竟 HTTP 是無狀態(tài)的協(xié)議,即開即用。
后來隨著互聯(lián)網(wǎng)的發(fā)展,服務(wù)端有一些即時(shí)消息需要立即展示給客戶端,早期的處理方式是通過客戶端定時(shí)發(fā)起 HTTP 請(qǐng)求,這種方式命中率較低且浪費(fèi)服務(wù)端資源?,F(xiàn)在有了 HTML5 之后不需要那么麻煩了,可以使用 websocket 或者 SSE。SSE 全稱 server-sent events 單項(xiàng)消息傳遞事件,相對(duì)于 websocket 這種雙向協(xié)議,SSE 較為輕量,它只支持服務(wù)端向客戶端推送消息。
1. 使用方式
1.1 創(chuàng)建實(shí)例
通過新建一個(gè) sse 對(duì)象可以創(chuàng)建一個(gè) SSE 實(shí)例,但是不要忘記檢測(cè)瀏覽器的支持情況:
if(typeof(EventSource)!=="undefined"){
var source = new EventSource("http://127.0.0.1/test.php");
}
上述示例實(shí)現(xiàn)了一個(gè)創(chuàng)建 SSE 對(duì)象的功能,創(chuàng)建之前需要檢測(cè)是否支持,目前 IE 之外的大部分瀏覽器都支持 SSE。sse 對(duì)象只有一個(gè)初始化參數(shù),用于指定服務(wù)器的 url。
1.2 接收消息
創(chuàng)建實(shí)例成功之后,通過監(jiān)聽 message 事件來實(shí)時(shí)獲取服務(wù)端的消息:
source.onmessage = function (event){
//處理業(yè)務(wù)請(qǐng)求
console.log(event.data)
}
1.3 服務(wù)端支持
服務(wù)器端需要對(duì)客戶端發(fā)起的 HTTP 請(qǐng)求做相應(yīng)的回復(fù),主要是將 HTTP 報(bào)文頭的 content-type 字段設(shè)置成 text/event-stream,下邊以 PHP 舉例:
header('content-type:text/event-stream');
while(true){
sleep(30000);
echo "message:".time();
//每隔半分鐘返回一個(gè)時(shí)間戳
}
1.4 其他事件
除了監(jiān)聽 message 事件用于獲取服務(wù)端的數(shù)據(jù)之外,還有 open 事件用于監(jiān)聽連接打開的狀態(tài), error 事件用于監(jiān)聽錯(cuò)誤信息。
2. 幾種常用的客戶端-服務(wù)器消息傳遞方式
- http 最常用的協(xié)議,用于客戶端主動(dòng)向服務(wù)器發(fā)送請(qǐng)求,單向傳遞;
- ajax HTTP 的擴(kuò)展版,底層還是 HTTP 協(xié)議,只不過客戶端是無刷新的;
- comet 也是基于 HTTP 封裝的,使用 HTTP 長(zhǎng)連接的方式,原理大致是將 HTTP 的timeout 設(shè)置較長(zhǎng),服務(wù)器有數(shù)據(jù)變化時(shí)返回?cái)?shù)據(jù)給客戶端,同時(shí)斷開連接,客戶端處理完數(shù)據(jù)之后重新創(chuàng)建一個(gè) HTTP 長(zhǎng)連接,循環(huán)上述操作(這只是其中一種實(shí)現(xiàn)方式);
- websocket 這是 HTML5 中的新標(biāo)準(zhǔn),基于 socket 的方式實(shí)現(xiàn)客戶端與服務(wù)端雙向通信,需要瀏覽器支持 HTML5;
- Adobe Flash Socket 這個(gè)也是使用 socket 的方式,需要瀏覽器支持 flash 才行,為了兼容老版本的瀏覽器;
- ActiveX object 只適用于 IE 瀏覽器;
目前尚沒有一種方式能兼容所有的瀏覽器,只能針對(duì)軟件的目標(biāo)客戶人群做一定的兼容。 - sse 服務(wù)端單向推送。
3. 適用場(chǎng)景
并非所有場(chǎng)景都適合使用 sse 處理,在消息推送接收不頻繁的情況下選用 ajax 輪詢或者 sse 或者 websocket 其實(shí)差別不太大。sse 應(yīng)該適用于服務(wù)端向客戶端發(fā)送消息頻繁而客戶端幾乎無需向服務(wù)端發(fā)送數(shù)據(jù)的場(chǎng)景下,例如:
- 新郵件通知;
- 訂閱新聞通知;
- 天氣變化;
- 服務(wù)器異常通知;
- 網(wǎng)站公告;
- 等等。
sse 的優(yōu)缺點(diǎn):
- SSE 使用 HTTP 協(xié)議,除 IE 外的大部分瀏覽器都支持;
- SSE 屬于輕量級(jí),使用簡(jiǎn)單;
- SSE 默認(rèn)支持?jǐn)嗑€重連;
- SSE 一般只用來傳送文本,二進(jìn)制數(shù)據(jù)需要編碼后傳送;
- SSE 支持自定義發(fā)送的消息類型。
4. 總結(jié)
本章介紹了 websocket 的輕量級(jí)版本 sse 協(xié)議,簡(jiǎn)述了 sse 協(xié)議的使用方法,對(duì)比了其他網(wǎng)頁中常用的消息推送方式以及他們的優(yōu)缺點(diǎn),這些協(xié)議涵蓋了大部分的使用場(chǎng)景,選用適合的協(xié)議類型可以避免不必要的資源和性能消耗。