小程序mqtt实现聊天功能
mqtt是什么?
MQTT是一个轻量级传输协议,它被设计用于轻量级的发布/订阅式消息传输,MQTT协议针对低带宽网络,低计算能力的设备,做了特殊的优化。是一种简单、稳定、开放、轻量级易于实现的消息协议,在物联网的应用下的信息采集,工业控制,智能家居等方面具有广泛的适用性。
谁发布,谁订阅?
MQTT服务器类似一个公告栏,里面张贴了各种广告。
张三跑过来说,凡是涉及足球的(/public/TEST/Soccer)的都发给自己(订阅)
第二天,李四过来贴广告了,主题是(/public/TEST/Soccer),发布的内容是“30号有比赛”
此时,公告栏会自动发短信给张三,发送的信息为 “30号有比赛”
张三:APP端;
李四:设备端;
公告栏:云端的MQTT服务器

mqtt优点?
1、MQTT更加简单:
MQTT是一种消息队列协议,使用发布/订阅消息模式,提供一对多的消息发布,解除应用程序耦合,相对于其他协议,开发更简单;
2、MQTT网络更加稳定
工作在TCP/IP协议上;由TCP/IP协议提供稳定的网络连接;
3、轻量级
小型传输,开销很小(固定长度的头部是 2 字节),协议交换最小化,以降低网络流量;适合低带宽,数据量较小的应用;
MQTT和Websocket的区别是什么?
-
MQTT是为了物联网场景设计的基于TCP的Pub/Sub协议,有许多为物联网优化的特性,比如适应不同网络的QoS、层级主题、遗言等等。 -
WebSocket是为了HTML5应用方便与服务器双向通讯而设计的协议,HTTP握手然后转TCP协议,用于取代之前的Server Push、Comet、长轮询等老旧实现。两者之所有有交集,是因为一个应用场景:如何通过HTML5应用来作为MQTT的客户端,以便接受设备消息或者向设备发送信息,那么MQTT over WebSocket自然成了最合理的途径了。
如何适用mqtt去实现聊天功能?
- 首先我们从前端布局样式开始
为了时时滚动到最新消息我们使用 scroll-view 标签包裹 使用它的
scroll-into-view属性我们绑定一个自定义id
如图:

我们在创建的元素上绑定一个 id属性,scroll-view 即可自动滚动到其对应位置。

以上就是几种不同消息类型的展示,我们先不考虑类型的样式,我们先来实现聊天左右分布的布局
推荐大家使用
flex布局去实现
左侧医生:display: flex;justify-content: flex-start; (默认属性)
右侧患者:display: flex;justify-content: flex-end;(尾部对齐)
样式方面主要也就是这两个属性,其他消息类型的,也是在这基础上做修改即可。
2.连接 mqtt
首先我们要引入依赖
var Paho = require('./utils/paho-mqtt-wx.js')
var Paho = require('./utils/paho-mqtt-wx.js')
/**
* 连接 mqtt
*/
connectMqtt() {
// let t = '异常断线';
var t = {}
t.i = this.globalData.connectParams.msgTopicName
t.c = 0
t.t = 3
// console.log(t, 98)
const message = new Paho.Message(JSON.stringify(t))
this.connectOptions = {}
//连接mqtt用户名
this.connectOptions.userName = api.mqttuser
//连接mqtt密码
this.connectOptions.password = api.mqttpass
//遗嘱消息 当客户端断开连接时,发送给相关的订阅者的遗嘱消息
this.connectOptions.willMessage = message
//心跳保持时间 是一种用于MQTT 的 长连接机制。
this.connectOptions.keepAliveInterval = 10
//断开连接时是否要清除session
this.connectOptions.cleanSession = this.globalData.connectParams.cleanSession
//设置如果连接丢失,客户端是否自动尝试重新连接到服务器
this.connectOptions.reconnect = false
//连接成功回调
this.connectOptions.onSuccess = this.onConnect
//连接失败回调
this.connectOptions.onFailure = this.failConnect
this.client = new Paho.Client('wss://' + this.globalData.connectParams.dnHost + '/mqtt', this.globalData.connectParams.clientId)
//当客户端失去连接时调用
this.client.onConnectionLost = this.onConnectionLost
this.client.onMessageArrived = this.onMessageArrived
//与服务器建立连接
this.client.connect(this.connectOptions)
},
onConnect(){
console.log('连接成功 - onSuccess')
//订阅
this.client.subscribe(this.globalData.connectParams.msgTopicName) //订阅
// var t = '上线';
var t = {}
t.i = this.globalData.connectParams.msgTopicName
t.c = 0
t.t = 0
const message = new Paho.Message(JSON.stringify(t))
message.destinationName = this.globalData.connectParams.statusTopicName
//发送上线消息
this.client.send(message)
}
failConnect(){
// 从新连接
console.log('连接失败 - onFailure')
}
onMessageArrived(message){
console.log('mqtt消息到达 - onMessageArrived:', message)
}
onConnectionLost(response){
// 从新连接
console.log('mqtt失去连接 - responseObject:', response)
}
以上我们完成mqtt连接操作,以及一些事件监听。
发送消息以及聊天记录缓存处理?

到这里就已经是聊天功能的核心了
首先是消息分组,消息按发送时间段去缓存分组,实现起来的思路大概就是,当我们
发送或者收到消息的时候
我们只需要拿当前你要发送或者你接受的消息发送时间(endTime)去与我们本地缓存记录的最新一条消息去做对比
//举个栗子
//最新消息的发送时间
let newEndtime = 1624418176356,
//本地缓存最新消息发送时间
oldEndtime = 1624418212889
//120000(毫秒)2分钟
newEndtime - oldEndtime <= 120000 ? 创建新分组 : 当前分组添加消息
时间分组的实现思路就是这样,我们只需要根据消息发送时间去计算,判断是不是两分钟内的消息,如果是我们直接在当前消息分组(
messageArr[messageArr.length-1].messages.Push)一条新消息,如果大于两分钟了,我们就直接从新创建一个分组,也就是messageArr.Push,Push过在把最新消息更新到本地历史消息即可。
历史消息上拉加载?
本地存储数据与服务端数据混合加载,因小程序本地存储限制我们前端只存100条聊天数据,本地的数据加载完以后,在上拉我们就要调用分页去获取历史消息了,
注意了:历史消息的分页,会有一个分页参数就是我们messageArr消息记录最后一条消息的endTime(发送时间),然后把服务端返回历史消息合并到我们messageArr里,消息加载总体就这些逻辑,
以上步骤我们就可以实现一个基本的聊天功能了 思路大体就是这样 有疑问的同学可以私信我
