微信小程序> 微信小程序实现实时聊天功能前端部分

微信小程序实现实时聊天功能前端部分

浏览量:3374 时间: 来源:weixin_34037173

小程序中创建webSocket连接

需求

  • 列表页需要实时获取新消息提示,详情页(聊天室)实现用户实时聊天

页面逻辑

列表页

首先在列表页开启ws服务,并监听开启/关闭事件,ws开启后,在wx.onSocketMessage监听消息

// 列表页onLoad(options) {  this.init();  // 监听接受消息  wx.onSocketMessage((res) => {})},init() {  //# 开启ws  this.openWS()},// 开启服务openWS() {  const token = wx.getStorageSync('token');  const app = getApp();  wx.connectSocket({    url: app.globalData.socketPath + '?sec-websocket-protocol=' + encodeURIComponent(token),    header: {      'content-type': 'application/json',      'from': 'wechatmini'    },    success() {},    fail() {}  })}复制代码
  1. ws要确保只连一个,统一在列表页监听服务开启/关闭,
  2. 服务断开后要重连服务,利用小程序进入详情后列表页不销毁特性,在列表页或详情页断线后都会执行列表页的重连事件
// # 列表页init() {    // # 1.ws要确保只连一个,用全局变量判断    !this.data.socketOpened && this.openWS();    // # 监听服务    wx.onSocketOpen((res) => {        console.log('WebSocket 已开启!')        this.data.socketOpened = true;    })    // # 重连    wx.onSocketClose((res) => {        console.log('WebSocket 已关闭!')        this.data.socketOpened = false;        // # 在列表页面重连服务        this.openWS()    })}复制代码

重连服务

为了减轻服务器的压力,防止连不上服务会一直请求连接服务,做了个延时处理,用reconnectDelay控制,成功后再重置。断线有2种情况,一是连接失败,二是连接成功后断线:

init() {    ...    wx.onSocketOpen((res) => {        console.log('WebSocket 已开启!')        this.data.socketOpened = true;        this.data.reconnectDelay = 0;    })        wx.onSocketClose((res) => {        console.log('WebSocket 已关闭!')        this.data.socketOpened = false;        // 在列表页面重连服务,重连失败调用时间+1s        setTimeout(() => {        this.openWS()        this.data.reconnectDelay += 1000        }, this.data.reconnectDelay);    })    ...}openWS() {    ...    wx.connectSocket({        ...    fail(res) {            console.log('连接失败');            // 在列表页面重连服务,重连失败调用时间+1s            setTimeout(() => {                this.openWS()                this.data.reconnectDelay += 1000            }, this.data.reconnectDelay);    }    })},复制代码

重连成功后,需要给服务端发送reconnect消息,根据和服务端约定,需要发送每个聊天的usif和该聊天最后一条消息id

// # 列表页init(){...    wx.onSocketOpen((res) => {    ...        // # msgList存储的是每个聊天最后一条消息对象    let len = this.data.msgList.length;    // # 发送重连消息    for (let i = len - 1; i >= 0; i--) {            let lastMsg = this.data.msgList[i];            // # util.sendMsg是公共方法,向服务端发送消息            util.sendMsg({            action: 'reconnect',            data: {                    index: lastMsg.id            },            usif: lastMsg.usif            })    }    })}// # util.jsfunction sendMsg({action,data,usif}) {    data['usif'] = usif    let msg = {    action: action,    data: data    }    wx.sendSocketMessage({    data: JSON.stringify(msg),    success: function () {},    })}复制代码

消息处理

列表页只要标志新消息,不涉及发送,只需要对接收的消息做处理

服务端约定的message自定义事件返回类型说明

操作含义
fail连接成功,但是获取用户信息失败(一般在redis连接失败,或者数据被清空时出现,此时需要重连)
online医生上线通知,此通知会广播所有用户(医生/普通用户)
push消息推送通知,收到此消息时可把数据插入到消息列表
pushback消息推送反馈,通知用户消息是否发送成功,成功则可插入列表,失败则需要重发
read消息已读通知,通知发消息的对象,对方已读此消息
reconnect断线重连时,此操作会返回对方最新发送的50条未读消息,可插入消息列表
online用户下线通知,此通知会广播所有用户,需要前端根据ID自行判断下线用户是否是在聊天的对象
// # 列表页// # 监听接受消息wx.onSocketMessage((res) => {    that.msgOperation({})})msgOperation({msgType,errcode = 0,data,errmsg}) {    let that = this    // # 根据不同消息类型做对应处理    switch (msgType) {    case 'push':        console.log('列表收到新消息');        // # Message是自定义类,用于对消息做初始化        data = new Message(data);         if (errcode == 0) {        // # taskList是存储聊天订单            for (let i = 0; i < that.data.taskList.length; i++) {                // # 收到相应订单的新消息则对该订单进行hasnews标识            if (data.booking_id == that.data.taskList[i].id) {                // # 如何只改变数组中某个值的属性值,中括号法                    var hasnews = 'taskList[' + i + '].hasnews'                    that.setData({                    [hasnews]: 1,                    })            }            }            // # 将新消息作为last_msg加到msgList,这一步是为断线重连发送消息做准备            that.data.msgList.forEach((item, idx) => {            if (item.booking_id == data.booking_id) {                    item = Object.assign({}, item, data)                    that.data.msgList.splice(idx, 1)                    that.data.msgList.push(item)            }            })            that.setData({            msgList: that.data.msgList            })        }        break;    case 'pushback':    // # 列表页不需要对发送反馈做处理        break;    case 'read':        //消息已读反馈,根据id标记消息为已读        data = new Message(data);        var msgid = data.id;        var length = that.data.msgList.length        // # msgList更新是为了??        for (let i = length - 1; i >= 0; i--) {            if (that.data.msgList[i].id == msgid) {            let is_read = "msgList[" + i + "].is_read";            that.setData({                    [is_read]: 1            })            }        }        // # 更新is_read, 消息已读/未读状态是根据taskList中的last_message来判断的        for (let i = that.data.taskList.length - 1; i >= 0; i--) {            if (that.data.taskList[i].last_message.id == msgid) {            let is_read = "taskList[" + i + "].last_message.is_read";            that.setData({                    [is_read]: 1            })            }        }        break;    case 'online':    console.log('医生上线');    break;    case 'reconnect':        console.log('断线重连', data);        // # 将收到的新消息加入msgList,作新消息处理        if (data.length) {            that.data.taskList.forEach((item, index) => {            for (let i = 0; i < data.length; i++) {                    if (data[i].booking_id == item.id) {                    var hasnews = 'taskList[' + index + '].hasnews'                    that.setData({                            [hasnews]: 1,                    })                    }                }            });        }    default:    }},复制代码

列表页主要负责服务开启/关闭,及对push/reconnect/read消息作处理

聊天室-详情页

服务端约定的send发送消息事件说明

操作含义
push消息推送(对方会在message事件中收到此消息)
read消息已读通知(对方会在message事件中收到此消息)
reconnect断线重连(会在自己客户端message事件中收到断线时未收到的消息)

操作:

  • 进入聊天室接口获取历史消息列表
  • 打开聊天室,对未读消息发送read
  • 点击发送后,发送push
  • 断线后重连成功,发送reconnect(列表页执行)
// # 聊天室onLoad() {    this.getMessageList();// 获取解读消息列表// # 监听接受消息 wx.onSocketMessage((res) => {        var data = JSON.parse(res.data);        // # 聊天框打开时才执行        if (this.data.chatOpened) {            this.msgOperation({                msgType: data.action,                data: data.data,                errmsg: data.errmsg,                errcode: data.errmsg            })        }    })},onShow() {    this.setData({    chatOpened: true,    })},onUnload() {    this.setData({        chatOpened: false    })},// # 点击发送按钮sendData(e) {    let data = {    msg_type: 1,    messages: e.detail.content,    usif: this.data.usif    };    wx.sendSocketMessage({    data: JSON.stringify({data, action: 'push'}),    success() {},    fail() {            wx.showToast({                title: '消息发送失败',                icon: 'none',                duration: 200            })    }    })},复制代码
  • 历史消息作已读处理,消息类型有文字,图片,语音,此处不另做分类处理
// 聊天室getMessageList(){...    module.messageList().then(res => {    ...        if (res.data.data.length) {            let msgList = [];            for (let i = 0; i < res.data.data.length; i++) {                let msg = new Message(res.data.data[i]);                // # 标记已读 c_user_type==1 为接收消息                if (msg.is_read == 0 && msg.c_user_type == 1) {                    msg.is_read = 1;                    util.sendMsg({                        action: 'read',                        data: {                            id: msg.id                        },                        usif: this.data.usif                    });                }                msgList.push(msg);            }            this.setData({ msgList })        }    })    }复制代码
  • 监听消息及处理,重点在于pushbackreconnect的处理
  • pushback后将消息推送到列表
  • reconnect时要将收到的消息追加到消息列表中
msgOperation({msgType,errcode = 0,data,errmsg}) {    let that = this    console.log('收到新消息', data);    switch (msgType) {        case 'push':        data = new Message(data);        // # 收到新消息push到消息列表        if (data.booking_id == that.data.booking_id) {            let msgList = that.data.msgList            msgList.push(data)            that.setData({                msgList: msgList,            })            console.log('若聊天框打开,则发消息告知已读');            util.sendMsg({                action: 'read',                data: data,                usif: that.data.usif            });        }        break;    case 'pushback':            data = new Message(data);            //消息发送成功的返回            if (errcode == 0) {                let msgList = that.data.msgList                //push到消息列表                msgList.push(data)                that.setData({msgList})            } else {                console.log('发送失败:', errmsg)            }            break;    case 'read':        // # 不处理        break;    case 'online':            console.log('医生上线');            break;    case 'reconnect':    if (errcode == 0) {                data.forEach(msg => {                    that.data.msgList.push(msg)                });                that.setData({                    msgList: that.data.msgList                })            };    default:    }},复制代码

其实,实时聊天前端部分逻辑还是相对简单的,主要在于

  1. 控制服务的开启/关闭,断线后的处理
  2. 对各种消息事件的处理
  3. 发送各类消息

版权声明

即速应用倡导尊重与保护知识产权。如发现本站文章存在版权问题,烦请提供版权疑问、身份证明、版权证明、联系方式等发邮件至197452366@qq.com ,我们将及时处理。本站文章仅作分享交流用途,作者观点不等同于即速应用观点。用户与作者的任何交易与本站无关,请知悉。

产品经理

手机 : 13312967497

擅长 : 小程序流量变现

扫码领取礼包

最新资讯

热门模板

  • 头条
  • 搜狐
  • 微博
  • 百家
  • 一点资讯
  • 知乎