适合场景:只需要发送一次数据,服务器可以实时返回数据进行渲染。
socket文件
javascript
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
};
页面中使用
javascript
<script>
import {
websocetObj
} from '@/common/websocket.js';
export default {
methods:{
//websocet函数回调:返回监听的数据
getWebsocetData(val) {
this.bids = JSON.parse(val).data.tick.bids
this.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>