關於在Vue中使用WebScoket的隨筆

橙序員 發表於 2022-01-12
Vue

宣告:請勿直接複製貼上抄襲文章,若有需要,請規範轉載,註明出處,謝謝!

---------------------------------------------------------------------------------------------------------

最近專案中使用到了webscoket,這個東西吧,用起來也很簡單。

但是我發現,這個東西會因為網路的不穩定而斷開連線,斷開就斷開吧,關鍵是斷開了,webscoket不會出現異常。

於是就要自己去檢測,這個有沒有掉線。

我的想法是,每隔30秒向伺服器傳送資訊,

每隔32秒去判斷有沒有收到訊息,如果沒有則判斷為斷開連線,進行重新連線。

因為我的技術能力還不是很強,所有程式碼在寫法上有些不足,或許有些冗餘,

但是功能的實現是沒有問題的,

話不多說,上程式碼

export default {
  data(){
    return {
      path:'',       // WebSocket的地址
      socket:'',     // WebSocket例項 
      times:0,       // 短線重新連線次數
      isConn:true,   // 配合次數進行自動重連
      heart:0,       // 接收定時器,用來檢測WebScoket是否斷線
      Tim:0,         // 用於判斷是否接收訊息的定時器
    }
  },
  mounted(){
    this.path = 'ws://82.157.123.54:9010/ajaxchattest'; // 測試地址,百度上可以搜尋到
    //this.path = 'ws://' + window.location.hostname + '/devices/history'; // 獲取瀏覽器當前地址,因為後臺ip可能不固定,如果固定可以寫死,就像上面那樣,但是如果ip動態,則可以使用這個,上線使用
    this.Init(this.path); // 掛載時,初始化資料,建立連線等
  },
  methods: {
    Init(path){
      this.socket = new WebSocket(path); // 進行連線,連線的結果和狀態在下面的onopen、onmessage、onclose
      let that = this; // 因為下面使用了普通函式,存在this指向問題,所以我就把vue的當前例項給that了,that的使用和this一樣,就看成this就行

      this.socket.onopen = function() {  
        console.log("WebScoket已經成功連線!"); 
        this.heart = setInterval(()=>{ that.socket.send('hello')},1000*30); // 每隔30秒就向伺服器傳送訊息
        that.times = 0; // 在連線成功的時候改變成初始狀態,如果重連就會增加
        that.isConn = true; // 同上,與上面的次數共同控制是否重連,我不可能一直嘗試重連,連線幾百次吧
      };

      this.socket.onmessage = function() { // 接收訊息,觸發此回撥
        console.log("接收到的訊息為:hello");
        if(that.Tim){ // 初始值為0,也就是false,第一次不會執行清理定時器
          clearTimeout(that.Tim);
        }
        that.Tim = setTimeout(()=>{ that.socket.close() },1000*33) // 只要接收到訊息就會建立一個定時器,定時器的內容是在33秒後關閉webscoket,但是如果在該時間內接收到訊息,那麼就會再次執行,會進入上面的if,
      }; 

      this.socket.onclose = function() {
        console.log("WebScoket已經斷開連線");
        if(this.heart !== 0){ 
          clearInterval(this.heart)
        }
        if(that.times < 5 && that.isConn){ // 每隔5秒就會重新連線,未連線成功就會次數增加,連線成功就會清零
          that.isConn = false; // 在定時器結束前,不允許再次執行該函式,這裡應該可以優化
          setTimeout(function(){ 
            that.times ++;
            console.log(`嘗試第${that.times}次重連!`)
            that.isConn = true;
            that.Init(that.path) // 執行嘗試重新連線
          },5000)
        }else{
          this.isConn = false; // 貌似可以優化
          this.socket.close(); // 徹底關閉
        }
      };

      this.socket.onerror = function() { // 這個刪了也不會報錯
        console.log('WebSocket連線發生異常!');
  
      };      
    },
}
}

 邏輯其實很簡單,就是有一點繞,宣告的變數稍微有點多,看懂了還是很簡單,

這些變數就像是一堆水龍頭,它是否放水,得要判斷,並且在不同的時候,給它不同的值。

如果不想搞懂也可以直接拿來用,關於時間地址改改就能用!

-----------------------------------------------------------------------------------------------------------------

測試的話,需要在vue檔案裡面寫,開啟控制檯,然後斷網聯網模擬真實情況,就可以除錯了

 

結果

關於在Vue中使用WebScoket的隨筆

(報錯是因為我手動開關了wifi,嘗試重連沒有問題,最後穩定連線,對接收訊息判斷,也沒有問題!)