IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> 记录uniapp微信小程序上使用websocket实现聊天 -> 正文阅读

[网络协议]记录uniapp微信小程序上使用websocket实现聊天

app.vue页面

里面的message.type 是和后台商量的类型。

1. websocket是进小程序就要启动的,在onLaunch里面但是肯定是在用户登录之后才启动,不然要报错。

2. 在onShow里面监听了一个emit,在用户登录之后,要启动websocket。

<script>
	export default {
		data() {
			return {
				wsUrl: "wss://school.qifuxiong.com/wss/",
				lockReconnect: false,  // 避免重复连接
				formId: null,
				toId: null,
				heartCheck : {
					timeout: 30000,
					timeoutObj: null,
					serverTimeoutObj: null,
					reset: () => {
						clearTimeout(this.heartCheck.timeoutObj);
						clearTimeout(this.heartCheck.serverTimeoutObj);
						return this.heartCheck;
					},
					start: () => {
						this.heartCheck.timeoutObj = setTimeout(() => {
							//这里发送一个心跳,后端收到后,返回一个心跳消息,
							//onmessage拿到返回的心跳就说明连接正常
							let heart = {
								type: "heart",
								fromId: this.formId
							}
							this.$store.state.wss.send({
								data: JSON.stringify(heart),
								success: () => {
									// console.log("发送一次心跳包", heart);
								}
							})
							this.heartCheck.serverTimeoutObj = setTimeout(() => {
								this.$store.state.wss.onOpen(_ => {
									this.$store.state.wss.close()
								})
							}, 70000) // 这里因为后台是60秒没反应就关闭,所以前端设置的是70秒关闭
							
						}, this.heartCheck.timeout)
					}
				}
			}
		},
		onLaunch: function() {
			console.log('App Launch')
			if(uni.getStorageSync('userInfo')) {
				this.createSocket(this.wsUrl)
				this.getMessageNum()
			}
		},
		onShow: function() {
			this.formId = uni.getStorageSync('userInfo').id
			uni.$on('openSocket', (data) => {
				this.formId = data.user_id
				this.createSocket(this.wsUrl)
				this.getMessageNum()
			})
			console.log('App Show')
		},
		onHide: function() {
			console.log('App Hide')
			this.$store.state.wss.onOpen(_ => {
				this.$store.state.wss.close()
			})
		},
		onUnhandledRejection(event) {
			console.error(event)
			event.preventDefault();
		},
		methods: {
			// 连接socket
			createSocket(path) {
				this.$store.state.wss = uni.connectSocket({
					url: path,
					success: (res) => {
						// console.log(res)
					},
					fail: (e) => {
						// 重连
						this.reconnect();
					},
				})
                // 这里需要nextTick一下,不然this.$store.state.wss获取的就是空
				this.$nextTick(() => {
					// 核心代码
					this.initEventHandle();
				})
			},// 初始化开始
			initEventHandle() {
				// console.log(this.$store.state.wss, this.formId) 
				this.$store.state.wss.onOpen((data) => {
					console.log("成功连接到: socket");
					this.heartCheck.reset().start();
				});
				this.$store.state.wss.onMessage((response) => {
					//如果获取到消息,心跳检测重置
					//拿到任何消息都说明当前连接是正常的
					this.heartCheck.reset().start();
					// json转化为obj
					let message = JSON.parse(response.data)
					console.log('服务端返回的数据', message)
					switch(message.type) {
						case "init":
							// 初始化发送当前人id,不然无法获取后台心跳
							let build = {
								type: 'bind',
								fromId: this.formId
							}
							this.$store.state.wss.send({
								data: JSON.stringify(build)
							})
							break;
						case 'letters':
                            // 这里是获取聊天数目
							this.getMessageNum();
							break;
						case "heart":
							// console.log('心跳不渲染任何信息')
							break;
					}
					this.$store.commit('setSocket', message) // 这句本来想用,后来没用,主要就是存在vuex里面
					uni.$emit('newSocketMsg', message) // 主要是这句,在聊天页面就会用到
					
				});
				this.$store.state.wss.onClose((close) => {
					console.log('连接关闭, 正在重连')
					this.reconnect()
				});
				this.$store.state.wss.onError((err) => {
					console.log('连接错误, 正在重连')
					this.reconnect()
				});
			},
			// 重连
			reconnect() {
				if(this.lockReconnect) return
				this.lockReconnect = true
				//没连接上会一直重连,设置延迟避免请求过多
				setTimeout(() => {
					this.createSocket(this.wsUrl)
					this.lockReconnect = false
				}, 5000)
			},
			// 获取数目
			getMessageNum() {
				this.$u.api.Meet.messageNum().then(res => {
					if(res && res.countNum !== 0) {
						uni.setTabBarBadge({
							index: 2,
							text: ''
						})
					}
				}).catch(e => {
					console.error(e)
				})
			}
		}
	}
</script>

chat.vue? 聊天页面

这里只展示跟websocket相关的代码,主要是接收消息和发送消息,注意我这里获取历史消息是一进页面就开始访问了接口;发送消息也是先调接口,毕竟数据要存在数据库,下次获取历史消息才有,后才通过websocket发送消息展示在页面上。

onLoad() {
    // 这里监听app.vue存的emit,初始化方法
    uni.$on('newSocketMsg', (data) => {
	    this.message = data
		this.initMethod()
	})
},
onShow() {
    // 拿聊天记录
	this.getHistoryMsg();
	// 点对点聊天判断对方是否在线
	let online = {
		type: 'online',
		to_id: this.toUser.id,
		from_id: this.userid
	}
	this.$store.state.wss.send({
		data: JSON.stringify(online)
	});
},
methods: {
    initMethod() {
		let message = this.message
		switch(message.type) {
		    case 'init':
				console.log('init')
				break;
			case 'text':
				console.log(message)
				let text = {
					id: message.id,
					from_id: message.from_id,
					to_id: message.to_id,
					content: message.data,
					type: 0,
					text: message.type,  // 表示文本信息(后台)
					is_read: message.is_read,
					pic: this.baseImgUrl + this.toUser.pic
				}
				this.talkList.push(text)
				this.$nextTick(()=>{
					uni.pageScrollTo({
						scrollTop: 999999,	// 设置一个超大值,以保证滚动条滚动到底部
							duration: 0
						});
					})
					break;
			case 'online':
				//  用户在线不在线, 涉及到一些业务场景需要处理
				//  如果对方上线了, 后端也会主动推送到这个里面来
				console.log('online:', message)
				break;
		}
	},
    // 发送信息
    send(){
				if(!this.content){
					uni.showToast({
						title:'请输入有效的内容',
						icon:'none'
					})
					return;
				}
				uni.showLoading({
					title:'正在发送'
				})
				let head_image = uni.getStorageSync('userInfo').avatar_url
				let timeStame = new Date().getTime()
				// 将当前发送信息 添加到消息列表。
				let data = {
					id: timeStame,
					content: this.content,
					type: 1,  // 1: 发送的
					pic: head_image.includes('http://') ? head_image : this.baseImgUrl + head_image
				}
				// 发送 调接口
				this.$u.api.Meet.chatWithOneFriend({
					to_id: this.toUser.id,
					message: this.content,
					// 类型: 0未读,1已读, 双方处于在线聊天中, 直接就是已读,对方不在线,就是未读
					is_read: this.message ? this.message.type == 'online' ? this.message.status.includes('对方不在线') ? 0 : 1 : 0 : 0
				}).then(res => {
					uni.hideLoading();
					// 页面显示
					this.talkList.push(data);
					this.$nextTick(()=>{
						// 清空内容框中的内容
						this.content = '';
						// 滚动到最新一条数据
						uni.pageScrollTo({
							scrollTop: 999999,	// 设置一个超大值,以保证滚动条滚动到底部
							duration: 0,
						});
					})
				}).catch(e => {
					uni.hideLoading();
				})
				
				this.$store.state.wss.send({
					data: JSON.stringify({
						data: this.content,
						type: 'say',
						from_id: this.userid,
						to_id: this.toUser.id
					})
				})
			}
}

  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2021-10-19 12:16:09  更:2021-10-19 12:17:38 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年7日历 -2024/7/1 11:24:14-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码