亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

websocket心跳重連實現(xiàn)探索(npm:websocket-heartbeat-js)

 更新時間:2023年07月04日 14:27:34   作者:子慕大詩人  
這篇文章主要為大家介紹了websocket心跳重連實現(xiàn)探索(npm:websocket-heartbeat-js),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

心跳重連緣由

提示:文章最下方有倉庫地址

websocket是前后端交互的長連接,前后端也都可能因為一些情況導(dǎo)致連接失效并且相互之間沒有反饋提醒。因此為了保證連接的可持續(xù)性和穩(wěn)定性,websocket心跳重連就應(yīng)運(yùn)而生。

在使用原生websocket的時候,如果設(shè)備網(wǎng)絡(luò)斷開,不會立刻觸發(fā)websocket的任何事件,前端也就無法得知當(dāng)前連接是否已經(jīng)斷開。這個時候如果調(diào)用websocket.send方法,瀏覽器才會發(fā)現(xiàn)鏈接斷開了,便會立刻或者一定短時間后(不同瀏覽器或者瀏覽器版本可能表現(xiàn)不同)觸發(fā)onclose函數(shù)。

后端websocket服務(wù)也可能出現(xiàn)異常,造成連接斷開,這時前端也并沒有收到斷開通知,因此需要前端定時發(fā)送心跳消息ping,后端收到ping類型的消息,立馬返回pong消息,告知前端連接正常。如果一定時間沒收到pong消息,就說明連接不正常,前端便會執(zhí)行重連。

為了解決以上兩個問題,以前端作為主動方,定時發(fā)送ping消息,用于檢測網(wǎng)絡(luò)和前后端連接問題。一旦發(fā)現(xiàn)異常,前端持續(xù)執(zhí)行重連邏輯,直到重連成功。

如何實現(xiàn)

在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();
};

這樣一般正常情況下失去連接時,觸發(fā)onclose方法,我們就能執(zhí)行重連了。

那么針對斷網(wǎng)情況的心跳重連,怎么實現(xiàn)呢,我們只需要定時的發(fā)送消息,去觸發(fā)websocket.send方法,如果網(wǎng)絡(luò)斷開了,瀏覽器便會觸發(fā)onclose。

簡單的實現(xiàn):

var heartCheck = {
    timeout: 60000,//60ms
    timeoutObj: null,
    reset: function(){
        clearTimeout(this.timeoutObj);
     this.start();
    },
    start: function(){
        this.timeoutObj = setTimeout(function(){
            ws.send("HeartBeat");
        }, this.timeout)
    }
}
ws.onopen = function () {
   heartCheck.start();
};
ws.onmessage = function (event) {
    heartCheck.reset();
}

如上代碼,heartCheck 的 reset和start方法主要用來控制心跳的定時。

什么條件下執(zhí)行心跳:

當(dāng)onopen也就是連接成功后,我們便開始start計時,如果在定時時間范圍內(nèi),onmessage獲取到了后端的消息,我們就重置倒計時,

距離上次從后端獲取到消息超過60秒之后,執(zhí)行心跳檢測,看是不是斷連了,這個檢測時間可以自己根據(jù)自身情況設(shè)定。

判斷前端websocket斷開(斷網(wǎng)但不限于斷網(wǎng)的情況):

當(dāng)心跳檢測執(zhí)行send方法之后,如果當(dāng)前websocket是斷開狀態(tài)(或者說斷網(wǎng)了),發(fā)送超時之后,瀏覽器的websocket會自動觸發(fā)onclose方法,重連就會立刻執(zhí)行(onclose方法體綁定了重連事件),如果當(dāng)前一直是斷網(wǎng)狀態(tài),重連會2秒(時間是自己代碼設(shè)置的)執(zhí)行一次直到網(wǎng)絡(luò)正常后連接成功。

如此一來,判斷前端斷開websocket的心跳檢測就實現(xiàn)了。為什么說是前端主動斷開,因為當(dāng)前這種情況主要是通過前端websocket.send來檢測并觸發(fā)的onclose,后面說后端斷開的情況。

我本想測試websocket超時時間,又發(fā)現(xiàn)了一些新的問題

1. 在chrome中,如果心跳檢測 也就是websocket實例執(zhí)行send之后,15秒內(nèi)沒發(fā)送到另一接收端,onclose便會執(zhí)行。那么超時時間是15秒。

2. 我又打開了Firefox ,F(xiàn)irefox在斷網(wǎng)7秒之后,直接執(zhí)行onclose。說明在Firefox中不需要心跳檢測便能自動onclose。

3.  同一代碼, reconnect方法 在chrome 執(zhí)行了一次,F(xiàn)irefox執(zhí)行了兩次。當(dāng)然我們在幾處地方(代碼邏輯處和websocket事件處)綁定了reconnect(),

所以保險起見,我們還是給reconnect()方法加上一個鎖,保證只執(zhí)行一次

目前來看不同的瀏覽器,有不同的機(jī)制,無論瀏覽器websocket自身會不會在斷網(wǎng)情況下執(zhí)行onclose,加上心跳重連后,已經(jīng)能保證onclose的正常觸發(fā)。  其實這是由于socket本身就有底層的心跳,socket消息發(fā)送不出去的時候,會等待一定時間看是否能在這個時間之內(nèi)再次連接上,如果超時便會觸發(fā)onclose。

判斷后端斷開:

    如果后端因為一些情況斷開了ws,是可控情況下的話,會下發(fā)一個斷連的通知,這樣會觸發(fā)前端weboscket的onclose方法,我們便會重連。

如果因為一些異常斷開了連接,前端是不會感應(yīng)到的,所以如果前端發(fā)送了心跳一定時間之后,后端既沒有返回心跳響應(yīng)消息,前端也沒有收到任何其他消息的話,我們就能斷定后端發(fā)生異常斷開了。

一點(diǎn)特別重要的發(fā)送心跳到后端,后端收到消息之后必須返回消息,否則超過60秒之后會判定后端主動斷開了。再改造下代碼:

var heartCheck = {
    timeout: 60000,//60ms
    timeoutObj: null,
    serverTimeoutObj: null,
    reset: function(){
        clearTimeout(this.timeoutObj);
        clearTimeout(this.serverTimeoutObj);
     this.start();
    },
    start: function(){
        var self = this;
        this.timeoutObj = setTimeout(function(){
            ws.send("HeartBeat");
            self.serverTimeoutObj = setTimeout(function(){
                ws.close();//如果onclose會執(zhí)行reconnect,我們執(zhí)行ws.close()就行了.如果直接執(zhí)行reconnect 會觸發(fā)onclose導(dǎo)致重連兩次
            }, self.timeout)
        }, this.timeout)
    },
}
ws.onopen = function () {
   heartCheck.start();
};
ws.onmessage = function (event) {
    heartCheck.reset();
}
ws.onclose = function () {
    reconnect();
};
ws.onerror = function () {
    reconnect();
};

PS:

    因為目前我們這種方式會一直重連如果沒連接上或者斷連的話,如果有兩個設(shè)備同時登陸并且會踢另一端下線,一定要發(fā)送一個踢下線的消息類型,這邊接收到這種類型的消息,邏輯判斷后就不再執(zhí)行reconnect,否則會出現(xiàn)一只相互擠下線的死循環(huán)。

結(jié)語

由于斷開等原因可能會導(dǎo)致發(fā)送的數(shù)據(jù)沒有發(fā)送出去,要保證數(shù)據(jù)不丟失的話,可以做消息回執(zhí),也就是a給b發(fā)送消息id=1,b返回收到id=1的消息,如果沒有回執(zhí)a可以再次發(fā)送消息id=1。

由上文可以看到,我們使用了前端發(fā)送ping,后端返回pong的這樣一種心跳的方式。也有一種方式是后端主動發(fā)送心跳,前端判斷是否超時。因為ws鏈接必須是前端主動請求建立連接,因此重連肯定是給前端來做,所以判斷重連邏輯都是寫在前端。

上面所說第二種方式是讓服務(wù)端發(fā)送心跳,前端來接收,這樣的方式會多節(jié)約一點(diǎn)帶寬,因為如果是前端發(fā)送心跳,后端需要返回心跳,也就是ping pong的過程會有兩次數(shù)據(jù)傳遞。  而后端來發(fā)送心跳的話,就只需要發(fā)送ping,前端不需要回應(yīng)。但是這樣造成了一個問題。前端需要和后端約定好心跳間隔,比如后端設(shè)置10秒發(fā)送一次心跳,那前端就需要設(shè)置一個安全值,比如距離上次收到心跳超過12秒還沒收到下一個心跳就重連。這種方式的問題在于調(diào)節(jié)時間就變得不那么靈活了,需要雙方都同時確定一個時間約定。后端的邏輯也會比較多一點(diǎn)。
而如果前端來發(fā)送ping 后端返回pong的話,那么間隔時間就只需要前端自己控制了。加上我的代碼把收到的任何后端信息都可以當(dāng)作是連接正常,從而重置心跳時間,這樣也節(jié)約了一些請求次數(shù)。
使用我這樣的方式,后端比較輕松,只需要在 onmessage 寫一段代碼,大概如下:

if(msg=='heartbeat') socket.send(anything);

封裝了一個npm包,歡迎使用

https://github.com/zimv/websocket-heartbeat-js

https://www.npmjs.com/package/websocket-heartbeat-js

以上就是websocket心跳重連實現(xiàn)探索(npm:websocket-heartbeat-js)的詳細(xì)內(nèi)容,更多關(guān)于websocket心跳重連的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • JavaScript本地存儲全面解析

    JavaScript本地存儲全面解析

    這篇文章主要為大家介紹了JavaScript本地存儲的全面解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-05-05
  • 利用javaScript處理常用事件詳解

    利用javaScript處理常用事件詳解

    這篇文章主要介紹了利用javaScript處理常用事件詳解,文章有非常詳細(xì)的代碼實踐,對學(xué)習(xí)js的小伙伴們有一定的參考價值,需要的朋友可以參考下
    2021-04-04
  • Redux 和 Mobx的選擇問題:讓你不再困惑!

    Redux 和 Mobx的選擇問題:讓你不再困惑!

    Redux 和 Mobx 都是當(dāng)下比較火熱的數(shù)據(jù)流模型,本文就開發(fā)者在面臨二者的選擇問題時,應(yīng)該如何選擇作了詳細(xì)介紹,需要的朋友可以參考下。
    2017-09-09
  • javascript進(jìn)階篇深拷貝實現(xiàn)的四種方式

    javascript進(jìn)階篇深拷貝實現(xiàn)的四種方式

    這篇文章主要為大家介紹了javascript進(jìn)階篇深拷貝實現(xiàn)的四種方式詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-07-07
  • 13個JavaScript 一行程序,讓你看起來就是個專家

    13個JavaScript 一行程序,讓你看起來就是個專家

    JavaScript 可以做很多好玩的事, 從復(fù)雜的框架到處理API,有太多的東西需要學(xué)習(xí)。但是,它也能讓我們只用一行就能做一些了不起的事情。今天的文章小編就為大家介紹13 個JavaScript 行程序,需要的朋友可以參考下
    2021-08-08
  • 前端JavaScript中的class類

    前端JavaScript中的class類

    這篇文章主要介紹了前端JavaScript中的class,類是用于創(chuàng)建對象的模板,JavaScript中的Class更多的還是語法糖,本質(zhì)上繞不開原型鏈,下面就來看看關(guān)于JavaScript class類的詳細(xì)內(nèi)容吧
    2021-10-10
  • 常用的JavaScript數(shù)組方法

    常用的JavaScript數(shù)組方法

    一說到JavaScript的數(shù)組,大家基本都能馬上想起pop()、push()、shift()、unshift()、indexof()等等,今天小編就給大家分享幾個開發(fā)中常用的js數(shù)組方法即他們的用法。需要的朋友可以參考下面文章的具體內(nèi)容
    2021-09-09
  • JS精髓原型鏈繼承及構(gòu)造函數(shù)繼承問題糾正

    JS精髓原型鏈繼承及構(gòu)造函數(shù)繼承問題糾正

    這篇文章主要為大家介紹了JS精髓原型鏈繼承及構(gòu)造函數(shù)繼承問題糾正,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-06-06
  • js解決移動端滾動穿透問題方案詳解

    js解決移動端滾動穿透問題方案詳解

    這篇文章主要為大家介紹了js解決移動端滾動穿透問題方案詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-07-07
  • javascript字符串單個字符訪問方法

    javascript字符串單個字符訪問方法

    這篇文章主要為大家介紹了javascript字符串單個字符訪問方法,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-07-07

最新評論