心跳重連緣由
在使用websocket過程中,可能會出現網絡斷開的情況,比如信號不好,或者網絡臨時性關閉,這時候websocket的連接已經斷開,
而瀏覽器不會執行websocket 的 onclose方法,我們無法知道是否斷開連接,也就無法進行重連操作。
如果當前發送websocket數據到后端,一旦請求超時,onclose便會執行,這時候便可進行綁定好的重連操作。
因此websocket心跳重連就應運而生。
如何實現
在websocket實例化的時候,我們會綁定一些事件:
var ws = new WebSocket(url); ws.onclose = function () { //something }; ws.onerror = function () { //something }; ws.onopen = function () { //something }; ws.onmessage = function (event) { //something }
如果希望websocket連接一直保持,我們會在close或者error上綁定重新連接方法。
ws.onclose = function () { reconnect(); }; ws.onerror = function () { reconnect(); };
這樣一般正常情況下失去連接時,觸發onclose方法,我們就能執行重連了。
那么針對斷網的情況的心跳重連,怎么實現呢。
簡單的實現:
var heartCheck = { timeout: 60000,//60ms timeoutObj: null, reset: function(){ clearTimeout(this.timeoutObj);
this.start(); }, start: function(){ this.timeoutObj = setTimeout(function(){ ws.send("HeartBeat", "beat"); }, this.timeout) } } ws.onopen = function () { heartCheck.start(); };
ws.onmessage = function (event) { heartCheck.reset(); }
如上代碼,heartCheck 的 reset和start方法主要用來控制心跳的定時。
當onopen也就是連接上時,我們便開始start計時,如果在定時時間范圍內,onmessage獲取到了服務器的消息,我們就重置倒計時,
所以在距離上次從服務器獲取到消息,閑置60秒之后我們才會心跳檢測,這個檢測時間可以自己根據自身情況設定。
當心跳檢測send執行之后,如果當前websocket是斷開狀態,發送超時之后,onclose方法便會被執行,重連也執行了。
如此一來,我們的心跳檢測就實現了。
后來,我本想測試websocket超時時間,又發現了一些新的問題
1. 在chrome中,如果心跳檢測 也就是websocket實例執行send之后,15秒內沒發送到另一接收端,onclose便會執行。那么超時時間是15秒。
2. 我又打開了Firefox ,Firefox在斷網7秒之后,直接執行onclose。說明在Firefox中不需要心跳檢測便能自動onclose。
3. 同一代碼, reconnect方法 在chrome 執行了一次,Firefox執行了兩次。當然我們在幾處地方(代碼邏輯處和websocket事件處)綁定了reconnect(),
所以保險起見,我們還是給reconnect()方法加上一個鎖,保證只執行一次
目前來看不同的瀏覽器,有不同的機制,無論瀏覽器websocket自身會不會在斷網情況下執行onclose,加上心跳重連后,已經能保證onclose的正常觸發。