在我們近年來的前端開發(fā)中其實(shí)很頻繁的使用這種數(shù)據(jù)更新模式螺戳。
只是對(duì)于前端來講排拷,初級(jí)前端開發(fā)在不更新技術(shù)的情況唱矛,很多人還是使用輪巡的方法去定時(shí)調(diào)用接口刷新數(shù)據(jù)。
而webScoket就是為了解決輪巡所產(chǎn)生的多種弊端而產(chǎn)生的音诫。
下面就是本人使用webScoket的vue項(xiàng)目代碼方案惨奕,也參考了其他代碼進(jìn)行優(yōu)化完善。
mounted() {
this.newWebSocket()
setTimeout(() => {
this.loading = false
}, 1000)
},
destroyed() {
this.websocket && this.websocket.close()
},
實(shí)現(xiàn)webSocket
newWebSocket() {
let _this = this
// let currentIp = this.$axios.defaults.baseURL.split('http://').join(''); //這里是取的vue項(xiàng)目中IP配置地址
// let currentIp = '192.168.1.251:8091'
var wsUrl = 'ws://' + currentIp + '/api/websocket/server';
//判斷當(dāng)前瀏覽器是否支持WebSocket
if ('WebSocket' in window) {
this.websocket = new WebSocket(wsUrl);
} else {
this.$message.error('Not support websocket');
};
//連接發(fā)生錯(cuò)誤的回調(diào)方法
this.websocket.onerror = function () {
console.log("出錯(cuò)");
_this.reconnect(wsUrl);
};
//連接成功建立的回調(diào)方法
this.websocket.onopen = function (event) {
heartCheck.reset().start(); //心跳檢測(cè)重置
console.log("open");
};
//接收到消息的回調(diào)方法
this.websocket.onmessage = function (event) {
heartCheck.reset().start();
// 這里是獲取到數(shù)據(jù)后我們的操作行為竭钝,對(duì)應(yīng)方法也就不需要寫了梨撞,對(duì)照后臺(tái)返回的數(shù)據(jù)格式進(jìn)行操作,注意:心跳檢測(cè)的時(shí)候香罐,后臺(tái)會(huì)返回我們定義好的文字(這里為ping)卧波,在我們接數(shù)據(jù)的時(shí)候需要考慮將此數(shù)據(jù)過濾掉。
if (event.data && event.data !== 'onMessage->ping') {
this.warningNotify(jsonObj.data.data)
}
}
};
//連接關(guān)閉的回調(diào)方法
this.websocket.onclose = function () {
console.log("close");
};
//心跳檢測(cè)
var heartCheck = {
timeout: 50000, //1分鐘發(fā)一次心跳
timeoutObj: null,
serverTimeoutObj: null,
reset: function () {
clearTimeout(this.timeoutObj);
clearTimeout(this.serverTimeoutObj);
return this;
},
start: function () {
var self = this;
self.timeoutObj && clearTimeout(self.timeoutObj);
self.serverTimeoutObj && clearTimeout(self.serverTimeoutObj);
self.timeoutObj = setTimeout(function () {
//這里發(fā)送一個(gè)心跳庇茫,后端收到后港粱,返回一個(gè)心跳消息,
//readyState 拿到返回的心跳的狀態(tài)readyState 1為正常
_this.websocket.readyState == 1 && _this.websocket.send("ping");
self.serverTimeoutObj = setTimeout(function () {//如果超過一定時(shí)間還沒重置旦签,說明后端主動(dòng)斷開了
_this.websocket.close(); //如果onclose會(huì)執(zhí)行reconnect查坪,我們執(zhí)行ws.close()就行了.如果直接執(zhí)行reconnect 會(huì)觸發(fā)onclose導(dǎo)致重連兩次
}, self.timeout)
}, this.timeout)
}
}
},
sendMsg() {
this.websocket && this.websocket.send('我的');
},
reconnect() {
let lockReconnect = false
if (lockReconnect) return;
lockReconnect = true;
setTimeout(() => { //沒連接上會(huì)一直重連,設(shè)置延遲避免請(qǐng)求過多
this.newWebSocket();
lockReconnect = false;
}, 2000);
}
對(duì)比網(wǎng)上的一些webScoket我進(jìn)行了一些優(yōu)化宁炫,優(yōu)化點(diǎn)如下偿曙。
1.webScoket連接錯(cuò)誤onerror的時(shí)候執(zhí)行reconnect方法重連,但是關(guān)閉onclose的時(shí)候不進(jìn)行重連羔巢。因?yàn)檫B接錯(cuò)誤并斷開會(huì)進(jìn)入對(duì)應(yīng)兩個(gè)方法望忆,如果兩個(gè)方法都進(jìn)行重連罩阵,當(dāng)切換路由時(shí)是會(huì)觸發(fā)onclose,會(huì)出現(xiàn)頁面已經(jīng)跳轉(zhuǎn)启摄,但還會(huì)重連webScoket的問題稿壁。
2.在_this.websocket.readyState == 1 && _this.websocket.send("ping")里,我將原本網(wǎng)上的_this.websocket && _this.websocket.send("ping")進(jìn)行修改歉备,因?yàn)楫?dāng)服務(wù)器端斷開時(shí)傅是,websocket其實(shí)還沒有銷毀,會(huì)導(dǎo)致報(bào)錯(cuò)WebSocket is already in CLOSING or CLOSED state.威创,所以直接修改用連接狀態(tài)readyState判斷落午。