在使用uniapp开发一个IM即时通讯系统时,需要用到websocket协议,uniapp提供了websocket的api,但是使用还是有点不太方便,在网上查找一番之后发现没有符合自己预期的,因此借鉴网上的并修改成自己想要的。
具体代码如下: ws.js
let isOpenSocket = false
let heartBeatDelay = 3000
let heartBeatInterval = null
let heartBeatText = "PING"
let reconnectTimes = 10
let reconnectInterval = null
let reconnectDelay = 3000
let wsUrl = "你的后端wsUrl"
let socketTask = null
let canReconnect = false
let ws = {
socketTask: null,
init,
completeClose
}
function init() {
socketTask = uni.connectSocket({
url: wsUrl,
complete: ()=> {}
})
socketTask.onOpen((res) => {
console.log("ws连接成功")
clearInterval(heartBeatInterval)
clearInterval(reconnectInterval)
isOpenSocket = true
canReconnect = true
heartBeat()
})
socketTask.onMessage((res) => {
console.log(res)
})
socketTask.onClose(() => {
if(isOpenSocket){
console.log("ws与服务器断开")
}else{
console.log("连接失败")
}
isOpenSocket = false
if(canReconnect){
reconnect()
canReconnect = false
}
})
ws.socketTask = socketTask
}
function heartBeat() {
heartBeatInterval = setInterval(() => {
console.log(heartBeatText)
send(JSON.stringify(heartBeatText));
}, heartBeatDelay)
}
function send(value) {
ws.socketTask.send({
data: value,
async success() {
console.log("消息发送成功")
}
});
}
function reconnect() {
clearInterval(heartBeatInterval)
if (!isOpenSocket) {
let count = 0;
reconnectInterval = setInterval(() => {
console.log("正在尝试重连")
init();
count++
if(count >= reconnectTimes){
clearInterval(reconnectInterval)
console.log("网络异常或服务器错误")
}
}, reconnectDelay)
}
}
function completeClose(){
clearInterval(heartBeatInterval)
clearInterval(reconnectInterval)
canReconnect = false
ws.socketTask.close()
}
module.exports = ws
使用时在main.js引入并绑定在Vue的prototype上,这样就可以做到全局变量了 main.js
import ws from 'ws.js'
Vue.prototype.$ws = ws
这个$ws 并不是最终用来操作的对象,$ws 内还有一个socketTask对象,并且$ws 对象中还有两个方法,init方法用来初始化socketTask,以及completeClose方法,用来彻底关闭websocket连接(不会重连)
当你在某个vue页面需要使用socketTask的话,需要调用$ws.init() ,因为已经将ws挂载到Vue上了,所以在vue页面可以使用this.$ws.init()
为什么不是在main.js就把socketTask对象初始化呢?
因为大部分情况下socketTask对象是需要在一定条件下才初始化的,比如在登录之后,才需要使用。而不是一打开APP就去连接后端的websocket服务器了。
当然,如果需要在main.js中把socketTask对象初始化,可以直接在main.js中调用init方法
关于socketTask的api具体可以去uniapp的官方文档找一找https://uniapp.dcloud.io/api/request/websocket
|