通用的WebSocket封裝

一個(gè)通用的websocket封裝實(shí)例手负,包括Api的回調(diào)嗓蘑,消息發(fā)送,連接關(guān)閉内舟。連接出錯(cuò)重連合敦,重連次數(shù)限制,重連超時(shí)停止操作等

/**
 * 
 * @param {配置} originalConfig 
 */
var wbst = /** @class */ (function (window) {
    //重連開始時(shí)間
    var reConnectBeginTime;
    //重連計(jì)數(shù)
    var reConnectNum = 1;
    //重連次數(shù)限定
    var limitReConnectNum = 3;
    //重連timer
    var reConnectTimer;
    // 構(gòu)造函數(shù)
    function websocket(originalConfig) {
        /**
         * originalConfig 
         *      url         string  //鏈接的url
         *      host        string  //主機(jī)名   有url則不傳验游,url需要有主機(jī)名
         *      protocols   string  //鏈接使用的協(xié)議 ws wss 默認(rèn)根據(jù)location進(jìn)行判斷 http ws or htps wss   
         *                              有url則不傳充岛,url需要有協(xié)議
         *      port        string  //例 ':8080' 端口號(hào) 有url則不傳保檐,url需要有端口
         *      message     string  //連接成功后默認(rèn)發(fā)送的數(shù)據(jù),并且在執(zhí)行send如果沒有傳遞參數(shù)崔梗,則默認(rèn)發(fā)送該值
         * 
         *      onopen: function () {}, //連接成功后觸發(fā)發(fā)
         *      onmessage: function () {},  //接收到消息觸發(fā)
         *      onclose: function () {},    //關(guān)閉后觸發(fā)
         *      onbeforeclose:function(){}  //關(guān)閉之前觸發(fā)
         *      onerror: function () {},    //發(fā)生錯(cuò)誤后觸發(fā)
         * 
         */
        /**
         * Wbst實(shí)例     close   //關(guān)閉連接
         *              send    //發(fā)送消息
         */
        //默認(rèn)配置參數(shù)
        var defaultConfig = {
            protocol: location.protocol == 'http:' ? 'ws:' : 'wss:',
            port: location.port,
            ws: null,
            timeout: 5000,
            onopen: function () { },
            onmessage: function () { },
            onclose: function () { },
            onerror: function () { },
            onbeforeclose: function () { }
        }
        //主機(jī)名
        var host = location.hostName;
        //路徑
        var pathName = location.pathname;
        //是否心跳狀態(tài)夜只,為false不可操作,等待重連
        this.isHeartFlat = false;
        //重連狀態(tài)
        this.isReconnect = false;

        originalConfig ?
            this.config = Object.assign({}, defaultConfig, originalConfig) :
            this.config = defaultConfig;

        this.config.protocol.indexOf(':') == -1 ? config.protocol += ':' : '';
        //如果沒有定義url蒜魄,則拼接url
        if (typeof this.config.url == 'undefined') {
            this.config.url = this.config.protocol + "http://" + host + ":" + this.config.port + pathName;
        }

        //發(fā)送消息函數(shù)
        this.send = function (message) {
            if (!this.ws) {
                console.error("websocket鏈接已關(guān)閉", this);
                return;
            }
            //如果沒有傳值扔亥,則默認(rèn)發(fā)送配置的默認(rèn)消息
            if (typeof message == 'undefined' && typeof this.config.message != 'undefined') {
                message = this.config.message;
            }
            //判斷心跳檢測(cè),連接是否存在或已連接
            if (!this.isHeartFlat) {
                // console.error("websocket未連接或出現(xiàn)故障或已斷開谈为,正在重新發(fā)送...");
                var _self = this;
                // var timeout = setTimeout(function () {}, 0);
                var timeout = setTimeout(function () {
                    var interval = setInterval(function () {
                        if (_self.ws.readyState === 1) {
                            clearTimeout(timeout);
                            clearInterval(interval);
                            timeout = null;
                            interval = null;
                            _self.send(message);
                            // console.log("websocket已發(fā)送請(qǐng)求");
                        } else {
                            clearTimeout(timeout);
                            clearInterval(interval);
                            console.error("websocket鏈接異常", this);
                        }
                    }, 100);
                }, 0);
                return;
            } else {
                this.ws.send(message);
            }
        }
        //關(guān)閉連接
        this.close = function () {
            if (!this.ws) {
                console.error("鏈接已關(guān)閉");
                return;
            }
            this.config.onbeforeclose(this.config, this.ws);
            this.ws.close();
        }

        this.init();
    }
    //初始化
    websocket.prototype.init = function () {
        var _self = this;

        window.WebSocket = window.WebSocket || window.MozWebSocket;
        if (!window.WebSocket) {
            console.error("瀏覽器不支持WebSocket");
            return;
        }

        var ws = new WebSocket(this.config.url);
        ws.onopen = function (e) {
            _self.onopen(e);
        };
        ws.onmessage = function (e) {
            _self.onmessage(e);
        };
        ws.onclose = function (e) {
            _self.onclose(e);
        };
        ws.onerror = function (e) {
            _self.onerror(e);
        }

        this.ws = ws;
        return;
    }
    //連接成功
    websocket.prototype.onopen = function (e) {
        this.isHeartFlat = true;
        this.config.onopen(e);
        if (typeof this.config.message != 'undefined') {
            this.ws.send(this.config.message);
        }
    }
    //接收消息回調(diào)
    websocket.prototype.onmessage = function (e) {
        this.config.onmessage(e);
    }
    //連接出錯(cuò)回調(diào)旅挤,默認(rèn)執(zhí)行重連操作
    websocket.prototype.onerror = function (e) {
        var _self = this;

        //心跳值為false
        this.isHeartFlat = false;
        this.config.onerror(e);

        if (reConnectNum <= limitReConnectNum) {
            //開始重連
            console.error('WebSocket連接出錯(cuò),正在重連...');
            clearTimeout(reConnectTimer);
            reConnectTimer = setTimeout(function () {
                if (reConnectNum == 1) {
                    reConnectBeginTime = new Date();
                }

                console.log('嘗試第' + reConnectNum + '次重連');
                _self.isReconnect = true;
                _self.reConnect();

                //如果心跳值為true伞鲫,則重連成功
                if (_self.isHeartFlat) {
                    clearTimeout(reConnectTimer);
                    reConnectTimer = null;
                }
            }, 2000);
        } else {
            console.error('重連次數(shù)超出設(shè)定值粘茄,不再重連,請(qǐng)檢查配置項(xiàng)');
        }
    }
    //關(guān)閉回調(diào)
    websocket.prototype.onclose = function (e) {
        this.isHeartFlat = false;
        this.config.onclose(e);
    }
    //重連操作
    websocket.prototype.reConnect = function () {
        //如果沒有觸發(fā)重連操作秕脓,則不執(zhí)行
        if (!this.isReconnect) return;

        //判斷重連超時(shí)柒瓣,若超時(shí),則不再重連
        if (new Date() - reConnectBeginTime > this.config.timeout) {
            console.error("websocket重連超時(shí)");
            this.isReconnect = false;
            //清除重連延時(shí)器
            clearTimeout(reConnectTimer);
            reConnectTimer = null;
            return;
        }

        //開始重連
        var _self = this;
        //重連計(jì)數(shù)器
        reConnectNum++;
        _self.init();
    }
    return websocket;
}(window, jQuery))
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末吠架,一起剝皮案震驚了整個(gè)濱河市芙贫,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌傍药,老刑警劉巖磺平,帶你破解...
    沈念sama閱讀 218,755評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異怔檩,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)蓄诽,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門薛训,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人仑氛,你說我怎么就攤上這事乙埃。” “怎么了锯岖?”我有些...
    開封第一講書人閱讀 165,138評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵介袜,是天一觀的道長。 經(jīng)常有香客問我出吹,道長遇伞,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,791評(píng)論 1 295
  • 正文 為了忘掉前任捶牢,我火速辦了婚禮鸠珠,結(jié)果婚禮上巍耗,老公的妹妹穿的比我還像新娘。我一直安慰自己渐排,他們只是感情好炬太,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著驯耻,像睡著了一般亲族。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上可缚,一...
    開封第一講書人閱讀 51,631評(píng)論 1 305
  • 那天霎迫,我揣著相機(jī)與錄音,去河邊找鬼城看。 笑死女气,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的测柠。 我是一名探鬼主播炼鞠,決...
    沈念sama閱讀 40,362評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼轰胁!你這毒婦竟也來了谒主?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,264評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤赃阀,失蹤者是張志新(化名)和其女友劉穎霎肯,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體榛斯,經(jīng)...
    沈念sama閱讀 45,724評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡观游,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了驮俗。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片懂缕。...
    茶點(diǎn)故事閱讀 40,040評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖王凑,靈堂內(nèi)的尸體忽然破棺而出搪柑,到底是詐尸還是另有隱情,我是刑警寧澤索烹,帶...
    沈念sama閱讀 35,742評(píng)論 5 346
  • 正文 年R本政府宣布工碾,位于F島的核電站,受9級(jí)特大地震影響百姓,放射性物質(zhì)發(fā)生泄漏渊额。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望端圈。 院中可真熱鬧焦读,春花似錦、人聲如沸舱权。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽宴倍。三九已至张症,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間鸵贬,已是汗流浹背俗他。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評(píng)論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留阔逼,地道東北人兆衅。 一個(gè)月前我還...
    沈念sama閱讀 48,247評(píng)論 3 371
  • 正文 我出身青樓,卻偏偏與公主長得像嗜浮,于是被迫代替她去往敵國和親羡亩。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 原文地址:http://www.ibm.com/developerworks/cn/java/j-lo-WebSo...
    敢夢(mèng)敢當(dāng)閱讀 8,914評(píng)論 0 50
  • 點(diǎn)擊查看原文 Web SDK 開發(fā)手冊(cè) SDK 概述 網(wǎng)易云信 SDK 為 Web 應(yīng)用提供一個(gè)完善的 IM 系統(tǒng)...
    layjoy閱讀 13,767評(píng)論 0 15
  • Swift1> Swift和OC的區(qū)別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴(yán)謹(jǐn) 對(duì)...
    cosWriter閱讀 11,103評(píng)論 1 32
  • 山高峰遠(yuǎn)煙霧漫危融, 林盛野深村更深畏铆。 人聲陣陣喊青天, 晨孩熟路尋奶吃吉殃。
    海南黑哥閱讀 262評(píng)論 2 12
  • 這不是一次愉快的旅行辞居,至少對(duì)我來說不是。一個(gè)小小的大巴車?yán)锶麧M了三四十個(gè)人蛋勺,男男女女瓦灶,神色各異,被送到一個(gè)固定的地...
    桜妧閱讀 289評(píng)論 0 0