適合場景:只需要發送一次數據,服務器可以實時返回數據進行渲染。
socket文件
let isSocketClose = false; // 是否關閉socket
let reconnectCount = 5; // 重連次數
// let heartbeatInterval = ""; // 心跳定時器
let socketTask = null; // websocket對象let againTimer = null; //斷線重連定時器let url = null;
let onReFn = null;
let onSucFn = null;
let onErrFn = null;/*** sockeUrl:websocet的地址* onReceive:消息監聽的回調* onErrorEvent:拋出錯誤的回調,且彈窗連接失敗的提示框* onErrorSucceed:拋出成功回調,主要用于隱藏連接失敗的提示框* */
const sokcet = (sockeUrl, onReceive, onErrorEvent, onErrorSucceed) => {url = sockeUrl;onReFn = onReceive;onErrFn = onErrorEvent;onSucFn = onErrorSucceed;isSocketClose = false;//判斷是否有websocet對象,有的話清空if (socketTask) {console.log('清空ws');socketTask.close();socketTask = null;// clearInterval(heartbeatInterval);}//WebSocket的地址// 【非常重要】必須確保你的服務器是成功的,如果是手機測試千萬別使用ws://127.0.0.1:9099【特別容易犯的錯誤】let url = sockeUrl// 連接socketTask = uni.connectSocket({url: url,success(data) {console.log('清空ws重連定時器');clearInterval(againTimer) //斷線重連定時器console.log("連接成功!");},fail: (err) => {console.log(url)console.log("報錯", err);}});// 連接打開socketTask.onOpen((res) => {console.log('WebSocket打開');uni.showToast({title: 'loading...',icon: 'none',})clearInterval(againTimer) //斷線重連定時器onErrorSucceed({isShow: false}) // 用于提示框的隱藏// heartbeatInterval && clearInterval(heartbeatInterval);// 10秒發送一次心跳// heartbeatInterval = setInterval(() => {// sendMsg('心跳ing')// }, 1000 * 5)})// 監聽連接失敗socketTask.onError((err) => {console.log('WebSocket連接打開失敗,請檢查', err);//停止發送心跳// clearInterval(heartbeatInterval)//如果不是人為關閉的話,進行重連if (!isSocketClose) {reconnect(url, onErrorEvent)}})// // 監聽連接關閉 -socketTask.onClose((e) => {console.log('WebSocket連接關閉!');// clearInterval(heartbeatInterval)console.log(isSocketClose, 123);if (!isSocketClose) {reconnect(url, onErrorEvent)}})// 監聽收到信息socketTask.onMessage((res) => {uni.hideLoading()// console.log(res, 'res監聽收到信息')let serverData = res.data//與后端規定好返回值分別代表什么,寫業務邏輯serverData && onReceive(serverData);});
}const reconnect = (url, onErrorEvent) => {console.log('進入斷線重連1', isSocketClose);clearInterval(againTimer) //斷線重連定時器// clearInterval(heartbeatInterval);socketTask && socketTask.close(); // 確保已經關閉后再重新打開console.log('進入斷線重連2', isSocketClose);socketTask = null;onErrorEvent({isShow: true,messge: '掃描頭服務正在連接...'})uni.showToast({title: 'loading...',icon: 'none',})// 連接 重新調用創建websocet方法againTimer = setInterval(() => {sokcet(url, onReFn, onErrFn, onSucFn)console.log('在重新連接中...');}, 1000)}const sendMsg = (msg) => { //向后端發送命令msg = JSON.stringify(msg)try {//通過 WebSocket 連接發送數據socketTask.send({data: msg});} catch (e) {console.log(e, "sendMsg Error");if (isSocketClose) {return} else {reconnect(url, onErrFn)}}
}
// 關閉websocket【必須在實例銷毀之前關閉,否則會是underfined錯誤】beforeDestroy() {websocetObj.stop();}const stop = () => {console.log("關閉定時器1");isSocketClose = true// clearInterval(heartbeatInterval);clearInterval(againTimer) //斷線重連定時器socketTask.close(); // 確保已經關閉后再重新打開socketTask = null;console.log("關閉定時器2", socketTask);
}const $debounce = function(fn, wait) {let timer = null;return function() {if (timer !== null) {clearTimeout(timer);}timer = setTimeout(fn, wait);}
}export const websocetObj = {sokcet,stop,sendMsg
};
頁面中使用
<script>import {websocetObj} from '@/common/websocket.js';export default {methods:{//websocet函數回調:返回監聽的數據getWebsocetData(val) {this.bids = JSON.parse(val).data.tick.bidsthis.asks = JSON.parse(val).data.tick.asks},//websocet函數拋錯: 返回錯誤信息 用于用戶提示getWebsocetError(err) {this.socketShow = err.isShow;this.webtext = err.messge;console.log('websocet函數拋錯', this.socketShow);},//websocet函數成功進入: 監聽連接狀態,在失敗的時候彈窗提示,具體需求看自身情況onErrorSucceed(val) {this.socketShow = val.isShow;websocetObj.sendMsg({"api": "market_depth","symbol": this.currencyShortParam})},websocket() {websocetObj.sokcet('ws://18.166.64.181:2346', this.getWebsocetData, this.getWebsocetError, this.onErrorSucceed) //請求地址},stopSocket() {websocetObj.stop()}},onShow() {this.websocket()},onHide() {this.stopSocket()},}</script>