适合场景:只需要发送一次数据,服务器可以实时返回数据进行渲染。
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>