一個(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))