![](/static/images/signal2.gif)
最近客户想做一个社团购物的软件,技术选型是采用uni-app开发的微信小程序,其中有一个功能是想开发一个买家和卖家沟通的功能模块,实现实时消息通知。
WebSocket是一种在单个TCP连接上进行全双工通信的协议。WebSocket通信协议于2011年被IETF定为标准RFC 6455,并由RFC7936补充规范。WebSocket API也被W3C定为标准。
WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。
在实际开发工作中,我们没有特别多的时间去实现一个scoket的完整功能,会利用到一些开源的插件,例如socket.io等,那么我们要如何区分在不同场景下怎么利用这些插件更好的为我我们的工作服务呢?
1、在H5页面中开发聊天功能,我们可以实际用到原生的js功能去对聊天的新增在做一些追加的操作,可以使用socket.io等类似的插件
2、在uni-app开发微信小程序时,由于我们的运行环境是小程序,我们最好是利用uni-app自带的socket的api来进行开发
3、对于做平台的小程序来讲,可以直接利用微信自带的客服功能,在微信公众平台配置自己的客服,可以说是既省时又省力
(1)开发过程中的思路设计:
1、在用户登陆时,根据用户的id创建一个全局的socket,与服务器建立联系
2、进入聊天页面,拉取用户联系过的人
3、点击联系卖家,即是创建买家和买家的socket联系,会先获取双方的聊天记录
4、自己发送消息和收到买家消息如何展示,在页面展示过程中,我们一般自己的聊天在右侧,收到别人的消息在左侧,可以通过判断 不同的id来展示相应的消息
5、监听对方发送的消息,自己发送的消息会push到消息数组中,然后监听对方发送过来的消息,再push到消息数组中,这样数组会及时更新消息展示
(2) 效果图片展示
(3) 代码展示,以下代码都是以vue的风格写的
message.js的代码
{{ item.waitCount }}
{{ item.targetUserName || '商城用户' }}
{{ item.newContentTime }}
{{ item.newContent && item.newContent.indexOf('oss') > -1 ? '[图片]' : item.newContent }}
chat.js的代码
class websocketUtil {
constructor(url, time) {
this.is_open_socket = false //避免重复连接
this.url = url //地址
this.data = null
//心跳检测
this.timeout= time //多少秒执行检测
this.heartbeatInterval= null //检测服务器端是否还活着
this.reconnectTimeOut= null //重连之后多久再次重连
try {
return this.connectSocketInit()
} catch (e) {
console.log('catch');
this.is_open_socket = false
this.reconnect();
}
}
// 进入这个页面的时候创建websocket连接【整个页面随时使用】
connectSocketInit() {
this.socketTask = uni.connectSocket({
url: this.url,
success:()=>{
console.log("正准备建立websocket中...");
// 返回实例
return this.socketTask
},
});
this.socketTask.onOpen((res) => {
console.log("WebSocket连接正常!");
uni.$emit('socket_open', 'WebSocket连接正常');
clearTimeout(this.reconnectTimeOut)
clearTimeout(this.heartbeatInterval)
this.is_open_socket = true;
this.start();
// 注:只有连接正常打开中 ,才能正常收到消息
this.socketTask.onMessage((res) => {
uni.$emit('chat', res.data);
});
})
// 监听连接失败,这里代码我注释掉的原因是因为如果服务器关闭后,和下面的onclose方法一起发起重连操作,这样会导致重复连接
uni.onSocketError((res) => {
console.log('WebSocket连接打开失败,请检查!');
uni.$emit('onSocketError', res);
this.is_open_socket = false;
this.reconnect();
});
// 这里仅是事件监听【如果socket关闭了会执行】
this.socketTask.onClose(() => {
console.log("已经被关闭了")
this.is_open_socket = false;
this.reconnect();
})
}
sendMsg(msg) {
console.log( msg, 'mssg')
//向后端发送命令
msg = JSON.stringify(msg);
try {
//通过 WebSocket 连接发送数据
this.socketTask.send({
data: msg
});
} catch (e) {
if (this.is_open_socket) {
return;
} else {
this.reconnect(url, onErrFn);
}
}
}
//重新连接
reconnect(){
//停止发送心跳
clearInterval(this.heartbeatInterval)
//如果不是人为关闭的话,进行重连
if(!this.is_open_socket){
this.reconnectTimeOut = setTimeout(()=>{
this.connectSocketInit();
},3000)
}
}
//开启心跳检测
start(){
this.heartbeatInterval = setTimeout(()=>{
this.data={value:"传输内容",method:"方法名称"}
console.log(this.data)
this.sendMsg(this.data);
},this.timeout)
}
//关闭连接
stop() {
this.is_open_socket = false;
this.heartbeatInterval = null;
}
}
module.exports = websocketUtil
chat.vue的代码
(4) 遇到的问题及解决办法
Q: 怎么避免你和某个联系 人的聊天会同步给其他联系人?
A:可以在监听对方发送的消息的时候,前端判断是否是和你正在聊天的用户,如果不是消息则不会被放到消息队列中,后端也要做一下校验,这样可以防止消息会发给其他人
Q: 在联系人页面,怎么显示消息通知有多少条?有性能比较好的方法吗?
A:可以联系人页面监听发送的消息,并且在当前列表中找到对应的数据,并更新消息数量,如果在消息列表中找不到对应的联系人,则是新联系人可以重新获取联系人列表,这样可以避免多次调取联系人来获取消息,并且能及时的显示消息的通知
以上就是今天要讲的内容,本文仅仅简单介绍了uni-app中开发消息模块的思路及方法,如果你有更好的想法可以和我分享