先看一下官方文档对 WebSocket 和 SocketTask 的定义。
初始化的时候,都是使用uni.connectSocket()
方法实现,但如果要使用WebsocketTask,需要注意这段话:
如果希望返回一个
socketTask
对象,需要至少传入 success / fail / complete 参数中的一个。var socketTask = uni.connectSocket({ url: 'wss://www.example.com/socket', //仅为示例,并非真实接口地址。 complete: ()=> {} });
如果没有传入 success / fail / complete 参数,则会返回封装后的 Promise 对象:Promise 封装
为了避免在切换页面时导致ws连接断开,我们可以将ws实例化时挂载至vue全局。
封装方法
// utils/websocket.js
export default class WebsocketTask {
/** 心跳定时器 */
#heartbeatInterval = null
/** 回调函数 */
#callback = null
/** ws状态 */
#websocketStatus = false
/** 是否主动关闭 */
#isClosed = false
constructor (url, interval) {
this.url = url
this.intervalTime = interval
// 实例化时立即连接ws。根据需求启用
// try {
// return this.initWebsocket()
// } catch (e) {
// this.#websocketStatus = false
// this.reconnect()
// }
}
/**
* 初始化Websocket
*/
initWebsocket() {
this.socketTask = uni.connectSocket({
url: this.url,
// 必要,否则会返回一个Promise
success: (status) => { }
})
this.socketTask.onOpen(() => {
clearTimeout(this.#heartbeatInterval)
this.#isClosed = false
this.#startHeartbeat()
this.socketTask.onMessage((msg) => {
let msgObj = JSON.parse(msg.data) || null
if (msgObj.type === 'pong') {
if (this.#websocketStatus === false) console.log('%c [Websocket] ', 'background: #2888D9;', '初始化成功')
this.#websocketStatus = true
} else {
console.log('%c [Websocket] ', 'background: #2888D9;', '接收消息:', msgObj)
this.#callback && this.#callback(msgObj)
}
})
})
// Websocket Closed Unexpected
this.socketTask.onClose(() => {
this.#websocketStatus = false
console.log('%c [Websocket] ', 'background: #2888D9;', '断开连接!')
// 非主动断开时自动重连
if (!this.#isClosed) this.reconnect()
})
}
/** 开始心跳 */
#startHeartbeat() {
this.#heartbeatInterval = setInterval(() => {
this.sendMessage({type: 'ping'})
}, this.intervalTime)
}
/**
* 发送消息
* @param {*} data 消息内容
*/
sendMessage (data) {
if (data.type !== 'ping') {
// 未就绪时稍后重试
if (!this.#websocketStatus) {
console.warn(' [Websocket] 未就绪', JSON.stringify(data))
return setTimeout(() => {
this.sendMessage(data)
}, this.intervalTime);
}
console.log('%c [Websocket] ', 'background: #2888D9;', '发送消息:', JSON.stringify(data))
}
this.socketTask.send({
data: JSON.stringify(data)
})
}
/** 设置回调 */
setCallback(cb) {
this.#callback = cb
}
reconnect() {
clearInterval(this.#heartbeatInterval)
if(!this.#websocketStatus) {
setTimeout(() => {
this.initWebsocket()
}, 3000);
}
}
/** 主动断开连接 */
disconnect() {
uni.closeSocket()
this.#websocketStatus = false
this.#isClosed = true
clearInterval(this.#heartbeatInterval)
}
}
全局挂载
// main.js
// ...
App.mpType = 'app'
Vue.prototype.$websocket = new WebsocketTask('wss://demo.com', 3000)
const app = new Vue({
...App
})
app.$mount()
// ...
使用方法
// demo.vue
// ...
<script>
// ...
onLoad() {
// 初始化ws
this.$websocket.initWebsocket()
// 设置回调
this.$websocket.setCallback((msg) => {
// 收到消息时的回调逻辑
console.log(msg)
})
},
onUnload() {
// 主动断开连接
this.$websocket.disconnect()
},
methods: {
sendMsg(msg) {
this.$websocket.sendMessage({value: 'hello, world'})
},
// ...
</script>
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。