uniapp中使用websocket实践(一)

1.根目录下新建tools目录,并在该目录下新建SocketManager.js文件:

let Manager = function(url) {
	//链接地址
	this.url = url
	//socket实例
	this.socket = null
	//是否链接
	this.isConnect = false
	//重连定时器
	this.timer = null
	//用户状态
	this.userStatus = null
    //token参数
	this.token = ''
    //业务逻辑的消息处理实现,多个业务逻辑
	this.messageEvent = []
    //是否手动关闭socket
	this.activeClose = false
}

//初始化uni.connectSocket实例,并绑定回调事件
Manager.prototype.init = function() {
	console.log('init');
	this.socket = uni.connectSocket({
		url: this.url,
		success(res) {
			console.log('init socket success', res)
		},
		fail(res) {
			console.log('init socket fail', res)
		}
	})

    //绑定事件
	this.addEvent()
}

//设置token参数
Manager.prototype.setToken = function(token) {
	this.token = token
}

//发送消息
Manager.prototype.send = function(data) {
	if (!this.isConnect) {
		return
	}
	data['token'] = this.token
	this.socket.send({
		data: JSON.stringify(data)
	})
}

//关闭socket
Manager.prototype.close = function(data) {
	if (!this.isConnect) {
		return
	}
	let that = this
	this.socket.close({
		code: 1000,
		success() {
			that.activeClose = true
		}
	})
}

//绑定事件
Manager.prototype.addEvent = function() {
	if (!this.socket) {
		return
	}

	let that = this

    //连接成功后回调
	this.socket.onOpen((res) => {
		console.log('onOpen', res);
		that.isConnect = true
		that.activeClose = false
		if (that.timer) {
			clearInterval(that.timer)
			that.timer = null
		}
		that.restoreUserStatus()
	})

    //收到消息时回调
	this.socket.onMessage((res) => {
		// console.log(res);
		let data = JSON.parse(res.data)
		that.messageEvent.forEach((item) => {
			if (item.business_id == data.business_id) {
				item.onMessage(data)
			}
		})
	})

    //socket关闭时回调
	this.socket.onClose((res) => {
		console.log('onClose', res);
		that.isConnect = false
		that.socket = null
		if(that.activeClose){
			console.log('手动关闭socket');
			return
		}
		let num = 1
		if (that.timer) {
			clearInterval(that.timer)
			that.timer = null
		}
		that.timer = setInterval(() => {
			 if (num == 10) {
			 	console.log('网络异常');
			 	clearInterval(that.timer)
			 	that.timer = null
			 	return
			 }
			console.log('第' + (num++) + '次重连...');
			that.init()
		}, 3000)
	})
}

//设置用户当前状态
Manager.prototype.setUserStatus = function(status) {
	this.userStatus = status
}

//添加业务逻辑实现
Manager.prototype.addMessageEvent = function(messageEvent) {
	let one = this.messageEvent.filter((item) => {
		return item.business_id == messageEvent.business_id
	})
	if (one.length > 0) {
		return
	}
	this.messageEvent.push(messageEvent)
}

//用户状态恢复
Manager.prototype.restoreUserStatus = function(){
	if(!this.userStatus){
		return
	}
	
	this.send(this.userStatus)
}

export const SocketManager = Manager

 

2.App.vue文件中挂载SocketManager到全局变量

<script>
	import { SocketManager } from '@/tools/SocketManager'
	export default {
		globalData:{
			socketManager: new SocketManager('wss://xxxxx'),
			token: 'xxxxx',
		},
		onLaunch: function() {
			console.log('App Launch')
		},
		onShow: function() {
			console.log('App Show')
		},
		onHide: function() {
			console.log('App Hide')
		}
	}
</script>

<style>
	/*每个页面公共css */
</style>

 

3.index.vue页面使用SocketManager实例

<template>
	<view class="content">
		<view>
			<button @click="sendMsg">send msg</button>
		</view>
		<view>
			<button @click="closeSocket">closeSocket</button>
		</view>
		<view>
			<button @click="connectSocket">connectSocket</button>
		</view>
	</view>
</template>

<script>
	export default {
		data() {
			return {
				title: 'Hello'
			}
		},
		onLoad() {
			getApp().globalData.socketManager.init()
			getApp().globalData.socketManager.setToken(getApp().globalData.token)
			getApp().globalData.socketManager.addMessageEvent({
				name: 'index',
				business_id: 2,
				onMessage(res) {
					console.log('index message', res);
				}
			})
		},
		methods: {
			sendMsg() {
				getApp().globalData.socketManager.send({
					business_id: 2,
					type: 'test',
					content: '测试'
				})
			},
			closeSocket() {
				getApp().globalData.socketManager.close()
			},
			connectSocket(){
				getApp().globalData.socketManager.init()
			}
		}
	}
</script>

<style>
	.content {
		display: flex;
		flex-direction: column;
		align-items: center;
		justify-content: center;
	}

	.logo {
		height: 200rpx;
		width: 200rpx;
		margin-top: 200rpx;
		margin-left: auto;
		margin-right: auto;
		margin-bottom: 50rpx;
	}

	.text-area {
		display: flex;
		justify-content: center;
	}

	.title {
		font-size: 36rpx;
		color: #8f8f94;
	}
</style>

 

posted @ 2024-07-15 15:07  tros  阅读(2146)  评论(0)    收藏  举报