(精華2020年5月21日更新) vue實戰篇 實時通訊websocket的封裝結合vue的使用

2b勿擾發表於2020-05-21
import webSocket from '../webSocket.js';
export default {
  isIosAndroid() {
    var u = navigator.userAgent;
    var isAndroid = u.indexOf('Android') > -1 || u.indexOf('Adr') > -1, //android終端
      isiOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/), //ios終端
      isChrome = u.indexOf('Safari'); //瀏覽器端
    return {
      isAndroid,
      isiOS,
      isChrome
    }
  },
  websocktSend(paramsObj) {
    // this --> store
    //這個是用來向後端websocket傳送資訊,傳送之前需要先判斷是否還處理連結狀態
    var userId = localStorage.getItem('userId');
    var sendMsg = () => {
      window.socketServer.send(JSON.stringify(paramsObj)); //給後端傳送資訊
    }
    if (window.socketServer.readyState == 1) {
      sendMsg();
    } else {
      // 這裡的this是$store,傳遞進來的
      // 這個this你並不知道
      webSocket.call(this, wsconPath[sceneParam] + userId).then(() => {
        sendMsg();
      });
    }
  },
  // 時間顯示的幾分鐘、幾小時、當天、昨天、前天以及更早的具體時間
  // 2019-12-07 09:58:23
  // JS計算兩個日期時間差,天 小時 分 秒格式
  showDiffTime: function (startDate) {
    if (!startDate) {
      return;
    }
    var startDate = startDate.replace(new RegExp(/-/gm), "/");
    var startDateB = new Date(startDate);

    var updateHour = startDateB.getHours(),
      updateMin = startDateB.getMinutes();

    updateHour = updateHour < 10 ? '0' + updateHour : updateHour;
    updateMin = updateMin < 10 ? '0' + updateMin : updateMin;
    var endDate = new Date(); //現在的時間
    var diff = endDate.getTime() - startDateB.getTime(); //時間差的毫秒數
    //計算出相差天數
    var days = Math.floor(diff / (24 * 3600 * 1000));
    // 1.當天,顯示:HH:MM
    // 2.昨天,顯示:昨天 HH:MM
    // 3.前天,顯示:前天 HH:MM
    // 4.更早,顯示:****年**月**日 HH:MM

    if (days > 0) {
      if (days == 1) {
        return "昨天 " + updateHour + ':' + updateMin;
      }
      if (days == 2) {
        return "前天 " + updateHour + ':' + updateMin;
      }
      if (days > 2) {
        return startDate.split(' ')[0] + ' ' + updateHour + ':' + updateMin;
      }
    }
    if (days == 0) {
      return updateHour + ':' + updateMin;
    }
  },
  //  像scroll,resize,keyup scroll等事件頻繁觸發會引發頁面的抖動甚至卡頓
  debounce(fn, delay) {
    delay = delay || 200;
    var timer = null;

    return function () {
      var arg = arguments;
      clearTimeout(timer);
      timer = setTimeout(function () {
        fn.apply(this, arg);
      }, delay);
    }
  },
}
//心跳檢測
var heartCheck = {
    timeout: 3000, //每隔三秒傳送心跳
    // num: 3,  //3次心跳均未響應重連
    timeoutObj: null,
    reset: function(){//接收成功一次推送,就將心跳檢測的倒數計時重置為30秒
        clearTimeout(this.timeoutObj);//重置倒數計時
        this.start();
    },
    start: function(){
        //啟動心跳檢測機制,設定倒數計時30秒一次
        this.timeoutObj = setTimeout(function(){
           //這裡傳送一個心跳,後端收到後,返回一個心跳訊息,
            //onmessage拿到返回的心跳就說明連線正常
            var userId = localStorage.getItem('userId');
            if(!userId){
                return;
            }
            window.socketServer.send(JSON.stringify({
                photographerObjectId:'',
                type:'6',
                leavingContent:'',
                photographerId:userId  //留言攝影師編號
            })); //給後端傳送資訊
        },this.timeout)
    }
    //onopen連線上,就開始start及時,如果在定時時間範圍內,onmessage獲取到了服務端訊息,
    //就重置reset倒數計時,距離上次從後端獲取訊息30秒後,執行心跳檢測,看是不是斷了。
}


/**建立連線 */
function createWSConnect(path){
    var _store = this;
    
    if (typeof WebSocket === "undefined") {
        alert("您的瀏覽器不支援socket");
    } else { 
        return new Promise((resolve,reject)=>{
            // 例項化socket
            var socket = new WebSocket(path);
            // 監聽socket連線
            socket.onopen = function(){
                console.log("socket連線成功!!!");   
                window.socketServer = socket;
                resolve(socket);
                //要不要把socket存放在store呢,看自己

                //心跳檢測啟動
                heartCheck.start();

            };
            socket.onclose = function (e) {
                console.log('websocket 斷開: ' + e.code + ' ' + e.reason + ' ' + e.wasClean)
                console.log(e);
                reconnect(path);
              }

            // 監聽socket錯誤資訊
            socket.onerror = function(){
                socket.close();
                reject();
                console.log("連線錯誤");
                reconnect(path);
            };
              // 監聽socket訊息,後端給到前端的資料
            socket.onmessage = function(res){
                if(res.data==1){
                    //檢測心跳
                    heartCheck.reset();
                    return;
                }   
                var data = res.data && JSON.parse(res.data); 
                // _store.dispatch('UpdateChatBadge',{count:data.count})
                updateMsgForType.call(_store,data);
                
            };
        })
     }
}

//重新建立連結
reconnect.lockReconnect = false;//避免重複連線
reconnect.timer = '';
function reconnect(url) {
    if (reconnect.lockReconnect) return;
    reconnect.lockReconnect = true;

    reconnect.timer && clearTimeout(reconnect.timer);
    //沒連線上會一直重連,設定延遲避免請求過多
    reconnect.timer = setTimeout(function () {     
        createWSConnect(url);
        reconnect.lockReconnect = false;
    }, 4000);
}

function updateMsgForType(data){
    if(data.error){
        this.$Toast(data.error);
        return;             
    }

    this.dispatch('UpdateChatBadge',{count:data.count})
    switch(data.type){
        case '0':  // 0 一對一交流文字
            this.dispatch('communication/addOneToOne',data.siteComm)
        break;
        case '1': //1 一對一交流圖片
            this.dispatch('communication/addOneToOne',data.siteComm)
        break;
        case '2': //2  未讀總條數 
        break;
        case '3': //撤回被刪除的資訊
            this.dispatch('communication/withdrawOneToOne',{count:data.siteComm})

        break;
        case '4': //單條代表刪除一對一資訊
            this.dispatch('communication/delOneToOne',data.siteComm)
        break;
        case '5': //批量刪除一對一資訊
            this.dispatch('communication/delAllOneToOne',data.siteComm)
        break;
    }
}
export default createWSConnect;

vue頁面的使用

utils.websocktSend.call(this.$store, paramsObj);

相關文章