websocket简介
- 使用 SocketTask 的方式去管理 webSocket 链接,每一条链路的生命周期都更加可控
- 可实现主动建立连接、心跳防断线机制、断线主动重连、提供主动断开的方法
一、如何使用 (uniapp Vue3)
</template>
<script setup>
import WS from './websocket'
import { onLoad, onUnload } from '@dcloudio/uni-app'
// 进入聊天页面初始化
let ws = null
onLoad((options) => {
ws = new WS({
// 连接websocket所需参数
data: { userId: options.userId },
// 首次连接成功之后,断线重新连接后也会触发(防止断线期间对方发送消息未接收到)
onConnected: () => {
// toDo
// 一般用于请求历史消息列表 getHistoryList()
},
// 监听接收到服务器消息
onMessage: (data) => {
// toDo
// 一般用于将最新的一条消息展示在页面上
}
})
})
// 发送消息
function sendMsg() {
uni.request({
url: '后端url',
data: {...},
success: () => {
// 发送成功后,上方onMessage会接收到最新消息
}
})
}
// 页面销毁,断开websocket
onUnload(() => {
// 主动关闭websocket
ws.close()
})
</script>
二、websocket类代码
// 心跳间隔、重连websocket间隔,5秒
const interval = 5000
// 重连最大次数
const maxReconnectMaxTime = 5
export default class WS {
constructor(options) {
// 配置
this.options = options
// WS实例
this.socketTask = null
// 正常关闭
this.normalCloseFlag = false
// 重新连接次数
this.reconnectTime = 1
// 重新连接Timer
this.reconnectTimer = null
// 心跳Timer
this.heartTimer = null
// 发起连接
this.initWS()
// 关闭WS
this.close = () => {
// 正常关闭状态
this.normalCloseFlag = true
// 关闭websocket
this.socketTask.close()
// 关闭心跳定时器
clearInterval(this.heartTimer)
// 关闭重连定时器
clearTimeout(this.reconnectTimer)
}
}
initWS() {
// this.options.data 连接websocket所需参数
const url = 'wss://后端url' + this.options.data.userId
this.socketTask = uni.connectSocket({ url, success() {} })
// 监听WS
this.watchWS()
}
watchWS() {
// 监听 WebSocket 连接打开事件
this.socketTask.onOpen(() => {
console('websocket连接成功!')
// 连接成功
this.options.onConnected()
// 重置连接次数
this.reconnectTime = 1
// 发送心跳
this.onHeartBeat()
// 监听消息
this.onMessage()
// 关闭Toast
uni.hideLoading()
})
// 监听websocket 错误
this.socketTask.onError(() => {
// 关闭并重连
this.socketTask.close()
})
// 监听 WebSocket 连接关闭事件
this.socketTask.onClose((res) => {
// 连接错误,发起重连接
if (!this.normalCloseFlag) {
this.onDisconnected(res)
}
})
}
// 监听消息
onMessage() {
// 监听websocket 收到消息
this.socketTask.onMessage((res) => {
//收到消息
if (res.data) {
this.options.onMessage(JSON.parse(res.data))
} else {
console('未监听到消息:原因:', JSON.stringify(res))
}
})
}
// 断开连接
onDisconnected(res) {
console('websocket断开连接,原因:', JSON.stringify(res))
// 关闭心跳
clearInterval(this.heartTimer)
// 全局Toast提示,防止用户继续发送
uni.showLoading({ title: '消息收取中…' })
// 尝试重新连接
this.onReconnect()
}
// 断线重连
onReconnect() {
clearTimeout(this.reconnectTimer)
if (this.reconnectTime < maxReconnectMaxTime) {
this.reconnectTimer = setTimeout(() => {
console.log(`第【${this.reconnectTime}】次重新连接中……`)
this.initWS()
this.reconnectTime++
}, interval)
} else {
uni.showModal({
title: '温馨提示',
content: '服务器开小差啦~请返回聊天列表重试',
showCancel: false,
confirmText: '我知道了',
success: () => {
uni.navigateBack()
}
})
}
}
/** @心跳 **/
onHeartBeat() {
this.heartTimer = setInterval(() => {
this.socketTask.send({
data: `heart:${this.options.data.userId}`,
success() {
console.log('心跳发送成功!')
}
})
}, interval)
}
}