vue全局使用WebSocket

vue接入websocket

首先就是網(wǎng)上的寫法有很多但是 都是需要創(chuàng)建一個對象進行相關的狀態(tài)回調(diào),有的是需要創(chuàng)建一個初始化方法進行相關的狀態(tài)回調(diào),然后看的我就一句話 都挺好的,反正就是需要你去創(chuàng)建對象接收發(fā)送消息,然后我就在這寫一個全局的使用的,因為我覺得大部分就是作為消息推送來用所以全局來用蠻好的。

websocket是什么:

首先是是基于TCP的 全雙工 通信的協(xié)議 然后就是websoket是通過客戶端向服務器建立連接,保持客戶端和服務器端雙向的通信的過程。相互收發(fā)消息

websocket的使用相關實例狀態(tài):

1>readyState屬性返回實例對象的當前狀態(tài)。共四種:

CONNECTING:值為0,表示正在連接。

OPEN:值為1,表示連接成功,可以通信了。

CLOSING:值為2,表示連接正在關閉。

CLOSED:值為3,表示連接已經(jīng)關閉,或者打開連接失敗。

2> onopen: 實例對象的onpen屬性,用于指定連接成功后的回調(diào)函數(shù)。

3>onclose: 實例對象的onclose屬性,用于指定連接關閉后的回調(diào)函數(shù)。

4>onmessage: 實例對象的onmessage屬性,用于指定收到服務器 數(shù)據(jù)后的回調(diào)函數(shù)。

5>send:實例對象的send()方法用于向服務器發(fā)送數(shù)據(jù)

具體使用:

1>首先創(chuàng)建一個全局文件: 在main.js 里面進行引入

// global.js 文件
export default {
    ws: {},
    setWs: function(newWs) {
        this.ws = newWs
    }
}
// main.js 文件
import global from './xx/global.js'
Vue.prototype.global = global

2> 在APP.vue 里面進行初始化 (回調(diào)有多個狀態(tài) 但是只寫了連接成功和失敗的方法)

//app.vue
oncerate(){
//初始化方法
 this.localSocket
 
}

methods(){ 

                        //app.vue
            localSocket() {
                let that = this;
                if ("WebSocket" in window) {
                    // console.log("您的瀏覽器支持 WebSocket!");
                    // location.host
                    that.ws = new WebSocket("ws://"+ 'ceshidizhi');
                    that.global.setWs(that.ws);
                    that.ws.onopen = function () {
                        console.log('websocket連接成功');
                    };

                    that.ws.onclose = function () {
                        // 關閉 websocket
                        console.log("連接已關閉...");
                        //斷線重新連接
                        setTimeout(() => {
                            that.localSocket();
                        }, 2000);
                    };
                } else {
                    // 瀏覽器不支持 WebSocket
                    console.log("您的瀏覽器不支持 WebSocket!");
                    this.openNotificationWithIcon('error', '瀏覽器', '您的瀏覽器不支持顯示消息請更換', 1,1)
                }
            },

}

3>然后就可以在其他頁面進行數(shù)據(jù)交互( 看代碼就能看出來 使用全局的對象進行數(shù)據(jù)獲取發(fā)送)

//pageA.vue

// 發(fā)送和接收消息
handdleMsg(msg) {
  let that = this;
  console.log(that.global.ws);
  if (that.global.ws && that.global.ws.readyState == 1) {
    console.log("發(fā)送信息", msg);
    that.global.ws.send(msg);
  }
  that.global.ws.onmessage = function(res) {
    console.log("收到服務器內(nèi)容", res);
  };
}

展示效果:我沒有截圖 就是連接成功后console里面會輸出值的 跑起來看看就知道了

注意:

在使用的時候,初始化不一定要放在 APP.vue里面 就像我需要在登錄成功之后拿到一個值,使用這個值去拼接地址,所以我就只能登錄后在進行連接,我就省了個事情,直接放在了頂部的組件里面。

長連接 在長時間不發(fā)送消息的時候,會自動斷開。原因是運維那塊使用了nginx服務,會配置一個時間段, 在這個時間里,如果一直滅有數(shù)據(jù)的傳輸,連接就會在這個時間之后自動關閉。因為我們無法控制用戶什么時候去觸發(fā)websocket消息的推送。所以下邊

心跳包機制:

//在onopen開始之后直接進行f方法調(diào)用 數(shù)據(jù)數(shù)據(jù)發(fā)送
start() {    // 發(fā)送心跳
      clearInterval(this.timeoutObj)
      this.timeoutObj = setInterval(() => {
        let that = this;
        let date = new Date()        
         if (that.global.ws && that.global.ws.readyState == 1) {
            console.log("發(fā)送信息", msg);
            that.global.ws.send(`發(fā)送心跳給后端${date}`);
        }
      }, 2 * 60 * 1000)
    }

代碼

// 創(chuàng)建websocket連接
            createWebSocket(){
                let that = this;
                that.webSocet = null;
                that.webSocet= new WebSocket(process.env.VUE_APP_SOCKET_URL);
                // console.log('that.webSocet',that.webSocet);
                if(that.webSocet.readyState == 0 && !that.timeoutnum){
                    that.timer = setInterval(() => {
                        if(that.timer_num < 3 && that.webSocet.readyState == 0 ){
                            that.timer_num++;
                        }else{
                            clearInterval(that.timer);
                            that.timer = null;
                            that.timer_num = 0;
                            // 只要不成功就連接
                            if(that.webSocet.readyState != 1){
                                that.reconnect();
                            }
                        }
                    }, 1000);
                }
                //鏈接成功時
                that.webSocet.onopen = function(){
                    //開啟心跳
                    that.start(); 
                }
                //收到消息時
                that.webSocet.onmessage = (msgInfo) => {
                    // console.log('接收到的消息',msgInfo);
                    that.UP_WEBSOCKETINFO({data:msgInfo.data,timer:msgInfo.timeStamp});
                    //收到服務器信息,心跳重置
                    that.reset();
                }
                //連接錯誤
                that.webSocet.onerror = function(){
                    console.log("WebSocket連接發(fā)生錯誤");
                    //重連
                    that.reconnect();
                };
                // 監(jiān)聽組件的銷毀
                that.$once('hook:beforeDestroy', () => {
                     if(that.webSocet.close){
                        that.webSocet.close();
                        that.webSocet.onclose = () =>{ 
                            console.log('web socket 鏈接已關閉'); 
                        };
                    }
                })
            },
            reconnect() {//重新連接
                let that = this;
                if(that.webSocet && that.webSocet.readyState == 1){
                    clearInterval(that.timeoutnum);
                    that.timeoutnum = null;
                    that.timeNum = 0;
                    return;
                }
                if(!that.timeoutnum) {
                    that.timeoutnum = setInterval(function () {
                        if(that.webSocet && that.webSocet.readyState == 1){
                            clearInterval(that.timeoutnum);
                            that.timeoutnum = null;
                            that.timeNum = 0;
                            return;
                        }   
                        //新連接
                        that.createWebSocket();
                        that.timeNum++;
                        if(that.timeNum >= 3){
                            clearInterval(that.timeoutnum);
                            that.timeoutnum = null;
                            that.timeNum = 0;
                        }
                    },1000);
                };
            },
            reset(){//重置心跳
                //清除時間
                clearTimeout(this.timeoutObj);
                clearTimeout(this.serverTimeoutObj);
                //重啟心跳
                this.start();
            },
            start(){//開啟心跳
                let that = this;
                that.timeoutObj && clearTimeout(that.timeoutObj);
                that.serverTimeoutObj && clearTimeout(that.serverTimeoutObj);
                that.timeoutObj = setTimeout(function(){
                    //這里發(fā)送一個心跳,后端收到后,返回一個心跳消息,
                    if (that.webSocet && that.webSocet.readyState == 1) {//如果連接正常
                        that.webSocet.send(
                            that.userInfo.userId + '-' + 
                            that.userInfo.userName + '-' +
                            that.userInfo.token
                        );
                    }else{//否則重連
                        that.reconnect();
                    }
                    
                }, that.timeout)
            },
...mapMutations('userInfo',{
                UP_WEBSOCKETINFO:'UP_WEBSOCKETINFO'
            })
[websocket關于禁止一個賬號多窗口鏈接的問題]

通過websocket的session.getSessionId()與oldSession.getSessionId()來equals判斷是否是新窗口。 如果不同不讓鏈接。

問題1.雖然新來的鏈接連不上,但是如果原窗口的鏈接斷線重連也會認為是新socket,也會被禁止鏈接。

解決方法: 原窗口鏈接時,原客戶端窗口先發(fā)關閉請求, 然后再連即可連上。

問題2. 如果上面原客戶端窗口關閉請求服務端沒有收到怎么辦? (網(wǎng)絡情況很復雜)

可以在onError和onClose中獲取到指定的oldSession,判斷isOpen(), 如果為false則說明已為僵尸鏈接,移除它即可。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

  • 第一部分 介紹 HTTP的缺點在于通信只能由客戶端發(fā)起,如果服務器有連續(xù)的狀態(tài)變化,客戶端要獲知就非常的麻煩,只能...
    Bing的天涯路閱讀 847評論 0 0
  • 一.WebSocket簡單介紹 隨著互聯(lián)網(wǎng)的發(fā)展,傳統(tǒng)的HTTP協(xié)議已經(jīng)很難滿足Web應用日益復雜的需求了。近年來...
    huoyl0410閱讀 5,866評論 3 2
  • 本文介紹 WebSocket 協(xié)議的使用方法。 一、為什么需要 WebSocket? 初次接觸 WebSocket...
    安易學車閱讀 413評論 0 0
  • 轉(zhuǎn)載自WebSocket,侵刪 WebSocket 教程 作者: 阮一峰 WebSocket 是一種網(wǎng)絡通信協(xié)議,...
    三十五歲是碼農(nóng)閱讀 515評論 0 0
  • 作者: 阮一峰 WebSocket 是一種網(wǎng)絡通信協(xié)議,很多高級功能都需要它。 本文介紹 WebSocket 協(xié)議...
    liwei_happyman閱讀 564評論 0 2

友情鏈接更多精彩內(nèi)容