關於在Vue中使用WebScoket的隨筆

  • 2022 年 1 月 12 日
  • 筆記

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

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

最近項目中使用到了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.onclose=()=>{ 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文件裡面寫,打開控制台,然後斷網聯網模擬真實情況,就可以調試了

 

結果

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

Tags: