通信技術:SSE設計方案(一)--- 前端Server-Sent Events概念講解和基礎類庫完善發布


好了,開篇還是要扯扯的,否則感覺這個技術講的么有那么凍人,嗯,這個晚上是有點冷了,秋衣秋褲大家都該加起來了,反正我不幫你買,妹子除外,嘻嘻。

之前幾篇博客,研究前端通信技術的第一層ajax技術,從最基礎的東西開始開發兼容,然后到最近的1.6版本吧,前前后后幾乎將ajax的所有能用的技術都研究過一遍了,在github上也得到了120+的star,在這里我要感謝大家的支持。主要這里為什么會這樣說呢,因為之前得到大家的認可和鼓勵,所以這次將進行前端通信技術的第二個階段的研究了,也就是前端的服務器推送 --- Server-Sent Events技術的研究。夜深了,不扯太多廢話了,我們直接進入主題。

概念講解:

  Server-Sent Events:簡稱SSE技術,也是前端es5支持的一種基於http協議的服務器推送技術。

  EventSource:js中承載SSE技術的主要核心方案和方法

  單工通道:只能一方面的數據導向,例如,在我們前端,我們通過瀏覽器向服務器請求數據,但是服務器不會主動推送數據給我們,這就是單通道

  雙工通道:類似webSocket這樣的技術,客戶端可以推數據給服務器,服務器也可以推數據給客戶端(下個版本實現)

  定點推送:服務器可以將數據針對單個客戶端推送(下個版本實現)

  多人推送:服務器可以將數據一次性推送給所有人(下個版本實現)

 

兼容性(看下圖):

  

 在所有IE系列中都不支持,其他瀏覽器幾乎都可以實現,所以為了實現萬惡的IE,會有如下2種方案

  1.  在其他瀏覽器上使用原生 EventSource 對象,而在 IE 上則使用簡易輪詢或 COMET 技術來實現;
  2.  使用 polyfill 技術,即使用第三方提供的 JavaScript 庫來屏蔽瀏覽器的不同。本文使用的是 polyfill 技術,只需要在頁面中加載第三方 JavaScript 庫即可。應用本身的瀏覽器端代碼並不需要進行改動。

  所以,這個方案,我會在最后一個版本和博客專門做兼容,暫時我們就忽略這個兼容性問題

  

對於其他通信技術的比較(也就是什么時候做這樣的技術選型)

  • sse是基於http協議的,對於現有項目的改造和支持是成本最低的方案。webSocket需要前后端全都換上新的協議支持
  • 對於推送的頻率來說,針對小於1次/1的推送,sse的使用最合適。大於1次的使用不划算,建議webSocket(考慮成本)
  • WebSocket 技術也比較復雜,包括服務器端和瀏覽器端的實現都不同於一般的 Web 應用。
  • 對於輪詢來說的話,每次的http協議的創建和銷毀對性能有點要求,況且對這個輪詢的時間點也不是能特別好的把握

  so,sse只是針對在適合他的地方才是最好的,這些點為大家做技術選型做些參考。

 

客戶端(瀏覽器)技術講解:

  在客戶端,也就是瀏覽器中,承載這個技術的就是EventSource了,下面直接上代碼吧

// 通用方案
create:function (options) {         // option為可配置參數
    var param = tool.initParam(options),sendData = '';          // 將用戶參數和默認參數合並

    if (param.data){        // 判斷是否傳遞參數給服務器,做參數處理
        tool.each(param.data, function (item, index) { sendData += (index + "=" + item + "&") }); sendData = sendData.slice(0, -1); } var es = new EventSource(param.url+'?'+sendData);  //創建EventSource鏈接
 es.addEventListener('open',function (e) {   // 注冊默認open事件
 param.openEvent(e) }); es.addEventListener('message',function (e) {    // 注冊默認message事件,如果服務器不指定回掉,則走這個
 param.messageEvent(e) }); es.addEventListener('error',function (e) {      // 注冊默認error事件
 param.errorEvent(e) }); // 創建用戶自定義事件
    if (param.customEvent.length > 0){ tool.each(param.customEvent,function (item) { es.addEventListener(item.name,item.callback); }) } }

  當然客戶端還有代表鏈接狀態的參數es.readyState:

    • 相當於常量EventSource.CONNECTING,表示連接還未建立,或者連接斷線。
    • 相當於常量EventSource.OPEN,表示連接已經建立,可以接受數據。
    • 相當於常量EventSource.CLOSED,表示連接已斷,且不會重連。

  message回調的返回值(可自己debugger看):

    data:服務器端傳回的數據(文本格式)。
    origin: 服務器端URL的域名部分,即協議、域名和端口。
    lastEventId:數據的編號,由服務器端發送。如果沒有編號,這個屬性為空。

  

  簡單解釋下:通過先new EventSource對象,建立連接,然后注冊一些默認事件和自定義事件,就結束了,客戶端就這么簡單。主要在服務端。

 

默認參數如下(有些參數預先定義下個版本使用):

var initParam = { url :'',                                //所鏈接的服務器地址
    data:'',                                //所發送的客戶端數據
    customEvent:[],                         //自定義事件 格式:[{name:'事件名稱',callback:function(res){}}]
    withCredentials:false,                 //是否發送跨域憑證
    serverTimeout:60000,                    //服務器http默認超時時間 待考慮:客戶端配置服務器時間,不安全
    clientConnection:3000,                  //設置瀏覽器重連時間,瀏覽器默認3s重連,
    openEvent:function () {},              //客戶端開始鏈接的事件
    messageEvent:function () {},           //客戶端接受到消息的事件(如不自定義系統默認)
    errorEvent:function () {}              //客戶端錯誤事件
}

 

服務器講解:

  對於建立連接的服務器,針對鏈接的客戶端有如下返回參數:

    :這是注釋        單獨一個冒號,代表服務器推送的一個注釋。(這個可解決http中的324,發送心跳包)

    id:11        代表數據標識符,代表當前數據的唯一標識(如果斷線,客戶端會在下次http head中發送這個標識,可做數據傳輸標記)

    data:我是誰    這個數據就是客戶端所接受到的數據(可推送格式化過的json數據)

    event:myEvent    服務器返回客戶端所執行事件(如不定義默認執行message事件)  

    retry:3000      客戶端在http超時斷開后多長時間重新連接

 

  對於服務器的這些參數的互相組合,是不是突然有種腦洞大開的感覺,下個版本將在這些參數中做文章,實現開頭所說的各種花樣技術

 

對於做測試中發現的許多問題拋出,可能你也會想到,這些問題都將在下幾個版本做完善

  • 客戶端兼容性問題(這個后面做)
  • 客戶端重連時間中,是否會丟失數據
  • 服務器的http協議超時時間的設置
  • 對於鏈接中出現的服務器返回超時
  • 如何做到單點推送,群推送
  • 服務器如何丟棄已斷開的鏈接
  • .......

 

測試如下(跳過ie系列)

  chrome:

   

  火狐:

  

  opera:

  

  safair:暫時沒有mac支持,淡定

 

所有都上傳github了,可直接拉去github上的東西做測試,地址:https://github.com/GerryIsWarrior/SSE不要忘記點顆star支持我,至少得到了你的認可,我會繼續研究下去。

  js-ommon:為一般開發使用,直接引入js文件的

  js-node:為node代碼,做簡易服務器用的

  js-npm:發的npm打包代碼,可npm i sse-js / yarn add sse-js 安裝

  index.html:為測試html頁面

 

總結:

這篇博客主要講解sse技術的基礎概念,因為基礎概念比較多,如果和第二版本一起搞上去,博文肯定很多很多,沒有耐心看下去了,所以這個博文只是讓大家對這個概念有所了解,知道這個東西是什么,能做什么,有啥新奇的玩意,能解決項目的什么問題。當然,我既然研究這個技術,當然為了保證將這個類庫寫好,至少可以到生產上使用這個類庫,當然這個路不是那么好走的,還需要不停的去研究和改正。正如我正在走的開發的路,都要我們一步一個腳印的去走的,共勉。

夜已深,大家晚安,明天發表這個博客...


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM