websocket 運用詳解

Summer_xiazi發表於2018-06-07

一、簡介:

websocket 建立網路長連結,最開始存在的意義就是為了解決我們使用 '輪詢' 的方式進行網路請求,輪詢的效率很低並且浪費網路資源,一般使用定時器來實現,而 websocket 的出現就解決了這個問題。它實現了伺服器端直接向客戶端推送訊息,並且客戶端也可以直接向服務端傳送訊息,這是一個真正的雙向平等對話。最典型的例子就是聊天室。

二、客戶端的簡單實現方法:

1.例項化一個 ws 物件 ,即:

var ws = new WebSocket(' url ');
複製程式碼

2.簡單的步驟:

①連結開啟的事件監聽:
ws.onopen = function(event) {   
    console.log("Connection open ..."); 
    ws.send("Hello WebSockets!");   // 向伺服器傳送資料
};
複製程式碼
②監聽訊息事件,當有訊息到達就會直接觸發:
ws.onmessage = function(event) {
    console.log( "Received Message: " + evt.data);
    ws.close();   // 關閉請求
};
複製程式碼
③監聽關閉事件,當使用close 時觸發:
ws.onclose = function(event) {
    console.log("Connection closed.");
};
複製程式碼
④錯誤監聽:
ws.onerror = function( err ){
    console.error(err)
}
複製程式碼

此處注意事項:

使用 onmessage 接受訊息的時候,我們可以指定資料型別,伺服器的資料可能是文字,也可能是二進位制資料, 以上就是一個最基本的客戶端的 websocket 實現;

三、WebSocket.readyState 例項物件的當前狀態:

通過 switch 可以直接檢視;

switch (ws.readyState){
    case WebSocket.CONNECTING:
        console.log('值為0,表示正在建立連結');
        break;
    case WebSocket.OPEN:
        console.log('值為1,表示連線成功,可以通訊');
        break;
    case WebSocket.CLOSING:
        console.log('值為0,表示正在關閉連結');
        break;
    case WebSocket.CLOSED:
        console.log('值為0,表示連線已經關閉或者開啟連線失敗');
        break;
    default:
        break;
}
複製程式碼

四、日常程式碼開發封裝:

在平時我們寫程式碼的時候,可以通過封裝一個類來實現 socket 長連結,具體程式碼如下:

class SocketManager {
    _socketMsgQueue = [];
	_isOpen = false;
	_messageCbs = [];

	constructor(url) {
	    if(!url) {
    		console.error('SocketManager: url is required');
    		return;
            }
		this._url = url;
		this._init();
        // 判斷是否有url  的存在,如果沒有就return,否則執行init () 方法;
	}

    _init() {
        // 建立WebSocket 連結:
        this._socketInstance = new WebSocket(this._url);
        // 開啟連結併傳送資料:
        this._socketInstance.onopen = () => {
            this._isOpen = true;
	    for (let i = 0; i < this._socketMsgQueue.length; i += 1) {
                    this.sendMessage(this._socketMsgQueue[i]);
            }
       		this._socketMsgQueue.length = 0;
       	};

		 this._socketInstance.onmessage = (e) => {
   		    for (let i = 0; i < this._messageCbs.length; i += 1) {
       		    this._messageCbs[i](e.data);
   			}
	 	};

 	    this._socketInstance.onclose = () => {
           	 this.destroy();
           	 this._init();
        };
    }
    //呼叫的回撥,這個地方比較繞,我想了大半天!!!和上述的onmessage 時間相對應			
    的。我們呼叫的時候,將一個函式出入,所以此時陣列中儲存的多個函式!!!所以在
    onmessage 中,我們拿到的e.data 就是資料使用for 迴圈,呼叫每一個函式!!! 
   	registerMessage(cb) {
        if (typeof cb === 'function') {
            this._messageCbs.push(cb);
        }
    }
    // 傳送資料,可通過this._isOpen 來判斷是否開啟了長連結;
    sendMessage(msg) {
        if (this._isOpen) {
            this._socketInstance.send(msg);
        } else {
            this._socketMsgQueue.push(msg);
        }
    }
    // 銷燬此次長連結
    destroy() {
        this._socketInstance.close();
        this._socketInstance.onmessage = null;
        this._socketInstance.onopen = null;
        this._socketInstance.onclose = null;
        
        delete this._socketInstance;
    }
}

export default SocketManager;
複製程式碼

五、封裝物件的呼叫:

1.首先引入我們封裝物件的檔案;import ....

2.由於我們封裝的時候是將這個物件暴露出去的,所以在引入之後,直接new 這個物件即可:

    const socketMng = new SocketManager(xcxSocketUrl);
複製程式碼

注意:這個地方的 url 是必須傳入的,在物件中也做了一個判斷!

3.執行方法:

socketMng.sendMessage('這是資料!!!');
socketMng.registerMessage((msg)=>{
    if(...){
        // 執行相應的操作!
    }
})
複製程式碼

注意:此時的這個箭頭函式,就是我們在registerMessage ()中傳入的值,即cb;

以上就是最近寫 WebSocket 所學習到的所有知識了,希望對大家有所幫助!!!不喜勿碰....

相關文章