在vue中使用SockJS實現webSocket通訊

最近接到一個業務需求,須要作一個聊天信息的實時展現的界面,這就須要和服務器端創建webSocket鏈接,從而實現數據的實時獲取和視圖的實時刷新.在此將個人實現記錄下來,但願能夠給有一樣需求的人一些幫助.廢話少說,下面我就來說一下個人實現過程:前端

前提

要進行文章中的代碼的測試,須要服務端端開發人員配合你,提供相關的通訊接口.來完成客戶端和服務端的通訊.實現通訊,咱們須要用到另個模塊sockjs-client模塊和stomjs模塊,接下來我會先對這兩個模塊作一個簡單的介紹.git

稍後我會寫一篇使用NodeJS+SockJS實現視屏彈幕的功能的文章,敬請期待~github

關於實時通訊

實現實時通訊,咱們一般有三種方法:web

  • ajax輪詢 ajax輪詢的原理很是簡單,讓瀏覽器每隔幾秒就像服務器發送一個請求,詢問服務器是否有新的信息.
  • http 長輪詢 長輪詢的機制和ajax輪詢差很少,都是採用輪詢的方式,不過纔去的是阻塞模型(一直打電話,沒收到就不掛電話),也就是說,客戶端發起連接後,若是沒有消息,就一直不返回response給客戶端.知道有新的消息才返回,返回完以後,客戶端再此創建鏈接,周而復始.
  • WebSocket WebSocket是HTML5開始提供的一種在單個TCP鏈接上進行全雙工通信的協議.在WebSocket API中,瀏覽器和服務器只須要作一個握手的動做,而後,瀏覽器和服務器之間就造成了一條快速通道。二者之間就直接能夠數據互相傳送,不須要繁瑣的詢問和等待. 從上面的介紹很容易看出來,ajax輪詢和長輪詢都是很是耗費資源的,ajax輪詢須要服務器有很快的處理速度和資源,http長輪詢須要有很高的併發,也就是同時接待客戶的能力.而WebSocket,只須要通過一次HTTP請求,就能夠與服務端進行源源不斷的消息收發了.

sockjs-client

sockjs-client是從SockJS中分離出來的用於客戶端使用的通訊模塊.因此咱們就直接來看看SockJS. SockJS是一個瀏覽器的JavaScript庫,它提供了一個相似於網絡的對象,SockJS提供了一個連貫的,跨瀏覽器的JavaScriptAPI,它在瀏覽器和Web服務器之間建立了一個低延遲,全雙工,跨域通訊通道. 你可能會問,我爲何不直接用原生的WebSocket而要使用SockJS呢?這得益於SockJS的一大特性,一些瀏覽器中缺乏對WebSocket的支持,所以,回退選項是必要的,而Spring框架提供了基於SockJS協議的透明的回退選項。SockJS提供了瀏覽器兼容性,優先使用原生的WebSocket,若是某個瀏覽器不支持WebSocket,SockJS會自動降級爲輪詢.ajax

stomjs

STOMP(Simple Text-Orientated Messaging Protocol) 面向消息的簡單文本協議; WebSocket是一個消息架構,不強制使用任何特定的消息協議,它依賴於應用層解釋消息的含義. 與HTTP不一樣,WebSocket是處在TCP上很是薄的一層,會將字節流轉化爲文本/二進制消息,所以,對於實際應用來講,WebSocket的通訊形式層級太低,所以,能夠在 WebSocket 之上使用STOMP協議,來爲瀏覽器 和 server間的 通訊增長適當的消息語義。跨域

STOMP與WebSocket 的關係:瀏覽器

  1. HTTP協議解決了web瀏覽器發起請求以及web服務器響應請求的細節,假設HTTP協議不存在,只能使用TCP套接字來編寫web應用,你可能認爲這是一件瘋狂的事情;
  2. 直接使用WebSocket(SockJS)就很相似於使用TCP套接字來編寫web應用,由於沒有高層協議,就須要咱們定義應用間發送消息的語義,還須要確保鏈接的兩端都能遵循這些語義;
  3. 同HTTP在TCP套接字上添加請求-響應模型層同樣,STOMP在WebSocket之上提供了一個基於幀的線路格式層,用來定義消息語義.

代碼實現

代碼中除了最基本的鏈接,還設置了一個定時器,每隔十秒發送一條數據到服務器端,若是發生錯誤,catch這個錯誤,從新創建鏈接.緩存

// 安裝並引入相關模塊
import SockJS from  'sockjs-client';  
import  Stomp from 'stompjs';
export default {
    data() {
      return {
        dataList: []
      };
    },
    mounted:function(){
      this.initWebSocket();
    },
    beforeDestroy: function () {
      // 頁面離開時斷開鏈接,清除定時器
      this.disconnect();
      clearInterval(this.timer);
    },
    methods: {
      initWebSocket() {
        this.connection();
        let self = this;
        // 斷開重連機制,嘗試發送消息,捕獲異常發生時重連
        this.timer = setInterval(() => {
          try {
            self.stompClient.send("test");
          } catch (err) {
            console.log("斷線了: " + err);
            self.connection();
          }
        }, 5000);
      },
      removeTab(targetName) {
        console.log(targetName)
      },
      connection() {
      // 創建鏈接對象
        this.socket = new SockJS('http://xxxxxx:8089/ws');//鏈接服務端提供的通訊接口,鏈接之後才能夠訂閱廣播消息和我的消息
        // 獲取STOMP子協議的客戶端對象
        this.stompClient = Stomp.over(this.socket);
        // 定義客戶端的認證信息,按需求配置
        var headers = {
          login: 'mylogin',
          passcode: 'mypasscode',
          // additional header
          'client-id': 'my-client-id'
        };
        // 向服務器發起websocket鏈接
        this.stompClient.connect(headers,(frame) => {
          this.stompClient.subscribe('/topic/chat_msg', (msg) => { // 訂閱服務端提供的某個topic
           consolel.log(msg.body);  // msg.body存放的是服務端發送給咱們的信息
          });
        }, (err) => {
            // 鏈接發生錯誤時的處理函數
            console.log(err);
        });

      },
      // 斷開鏈接
      disconnect() {
        if (this.stompClient != null) {
          this.stompClient.disconnect();
          console.log("Disconnected");
        }
      }
    }
};
複製代碼

結語

不知道我是否有寫明白,我才疏學淺,表達能力有限,若是有不明白的地方,可發送疑問到個人郵箱2510909248@qq.com,另外若是有什麼好的意見或者建議,也歡迎騷擾~~~服務器

參考連接

websocket:支持 前端鏈接 + 訂閱websocket

SockJS簡單介紹

STOMP 客戶端 API 整理

往期文章

postMessage可太有用了

Expires, Last-Modified, Etag緩存機制

手把手教你製做表格表頭懸浮(table-header-fixed)

相關文章
相關標籤/搜索