前言:我这里采用的是旧的类构造方法,大家可以查看使用新的类构造方法来写,可看阮一峰老师的ES6:https://es6.ruanyifeng.com/#docs/class

 import interfaces from "../interface/interfaces.js"
 import dayjs from "dayjs"
export default function chatWebsocket(userId,contactId, token, that) {
 this.socketTask = null;
 this.webSocketPingTimer = null;
 this.webSocketReconnectCount = 0;
 this.webSocketIsReconnect = true;
 this.webSocketIsOpen = true;
 this.userId = contactId; //接收者
 this.token = token;
 this.senderId = userId; //发送者
 this.msg = null,
 this.sendMsgStatus = false;
 this.that = that;
 // chatWebsocket.prototype.getMsg = function() {
 //  return this.msg;
 // },
 chatWebsocket.prototype.webSocketInit = function() {
  // 创建一个this.socketTask对象【发送、接收、关闭socket都由这个对象操作】
  this.socketTask = uni.connectSocket({
   url: `ws://ip地址:端口号/insoApp/websocket/talk/${this.userId}`, //es6拼接字符串、反引号
   success(data) {
    console.log("websocket连接成功");
   },
  });
  
  // ws连接开启后登录验证
  this.socketTask.onOpen((res) => {
   console.log("WebSocket连接正常打开中...!");
   this.webSocketPing();
   // 注:只有连接正常打开中 ,才能正常收到消息
   this.socketTask.onMessage((res) => {
    console.log(res);
    if(res) {
     const result = JSON.parse(res.data);
     console.log("对方发送的内容",result);
     if(result.data.contactId == this.userId) {
      console.log(result.data);
      uni.$emit('updateMsg', result.data);
     }
     // uni.$emit('updateMsg', Object.assign({}, this.msg));
    }
    
    // this.that.$store.commit('setChatRecordMsg', Object.assign({}, this.msg));
   });
  })
  
  // 链接开启后登录验证
  this.socketTask.onError((errMsg) => {
   console.log(errMsg)
   console.log("ws连接异常")
   this.webSocketClose();
  });
  
  // 链接开启后登录验证
  this.socketTask.onClose((errMsg) => {
   console.log(errMsg)
   console.log("ws连接关闭")
   this.webSocketClose();
  });
  
 },
 
 // 断开连接时
 chatWebsocket.prototype.webSocketClose = function(webSocketIsOpen = false) {
  if(webSocketIsOpen == true) {
   this.socketTask.close();
   this.webSocketIsReconnect = false;
  }
  // 修改状态为未连接
  this.webSocketIsOpen = false;
  this.webSocket = null;
  // 判断是否重连
  if (
   this.webSocketIsReconnect &&
   this.webSocketReconnectCount === 0
  ) {
   // 第一次直接尝试重连
   this.webSocketReconnect();
  }
 },
 
 // 定时心跳
 chatWebsocket.prototype.webSocketPing = function() {
  this.webSocketPingTimer = setTimeout(() => {
   if (!this.webSocketIsOpen) {
    return false;
   }
   console.log("心跳");
 //   const payload = {
 
 //    type: 0
 
 //   };
   // this.webSocketSend("11");
   clearTimeout(this.webSocketPingTimer);
   // 重新执行
   this.webSocketPing();
  }, this.webSocketPingTime);
 
 },
 
 // WebSocket 重连
 chatWebsocket.prototype.webSocketReconnect = function() {
  return;
  if (this.webSocketIsOpen) {
   return false;
  }
  console.log("第"+this.webSocketReconnectCount+"次重连")
  this.webSocketReconnectCount += 1;
  // 判断是否到了最大重连次数 
  // if (this.webSocketReconnectCount >= 10) {
  //  this.webSocketWarningText = "重连次数超限";
  //     return false;
  // }
  // 初始化
  console.log("开始重连")
  this.webSocketInit();
  // 每过 5 秒尝试一次,检查是否连接成功,直到超过最大重连次数
  let timer = setTimeout(() => {
   this.webSocketReconnect();
   clearTimeout(timer);
  }, 5000);
 },
 
 // 发送ws消息
  chatWebsocket.prototype.webSocketSend = async function(sendContent, accessoryPath) {
  let now = new Date();
  now = dayjs(now).format('YYYY-MM-DD HH:mm:ss');
  console.log("现在时间",now);
  await uni.request({
   url: interfaces.push,
   method: "POST",
   data: {
        token: this.token,
        userId: this.senderId, //发送者
        contactId: this.userId, //接收者
        sendTime: now, //发送时间
        sendContent: sendContent, //发送内容
     accessoryPath: accessoryPath
   },
   success: (res) => {
    console.log(res.data);
    this.msg = res.data.data;
    this.that.$store.commit('setChatRecordMsg', Object.assign({}, this.msg));
   }
  });
 }
}

总结

在开发双向聊天功能的过程中,出了很多问题,最严重的就是数据源错乱,因为我是多个websocket一起开着的,一开始采用以下写法最后才发现是共用了同一个对象(地址指向相同),所以改用了上面的类构造写法。还有一个问题就是双向发送消息变成了单向聊天,经后端检测验证是url路径出了问题,只能够填写一个userId,不能同时写发送人和接收人Id,所以只需要写上我自己的id(开启自己的websocket,所有好友发送过来的消息都由这个websocket接收),我在接收对方发送过来的消息就作了判断,当发送人id == 联系人id,我才监听反馈给聊天页面。

### 废弃代码 废弃代码 废弃代码 废弃代码 大家以史为鉴 ####

import dayjs from "dayjs"
import http from "./request.js"
import $store from "../store/index.js"
export default {
 config: {
  url: '',
  socketTask: null,
  webSocketPingTimer: null,
  webSocketPingTime: 50000, // 心跳的间隔,当前为 10秒,
  webSocketReconnectCount: 0,
  webSocketIsReconnect: true,
  webSocketIsOpen: true,
  userId: null, //接收者
  token: '',
  senderId: null, //发送者
  msg: null,
  sendMsgStatus: false,
  isChat: false,
 },
 webSocketInit(url,that) {
  that.config.url = url;
  // 创建一个this.socketTask对象【发送、接收、关闭socket都由这个对象操作】
  that.config.socketTask = uni.connectSocket({
   url: that.config.url,
   success(data) {
    console.log("websocket连接成功");
   },
  });
  
  // ws连接开启后登录验证
  that.config.socketTask.onOpen((res) => {
   console.log("WebSocket连接正常打开中...!");
   // this.webSocketPing(that);
   // 注:只有连接正常打开中 ,才能正常收到消息
   that.config.socketTask.onMessage((res) => {
    const result = Object.assign({}, JSON.parse(res.data));
    console.log("聊天发送接收内容",JSON.stringify(that.config));
    if(!that.config.isChat) { //消息首页
     $store.commit('setChatRecordMsg', result.data);
     if(result.data.unreadCount > 0) {
      uni.setTabBarBadge({
       index: 1,
       text: result.data.unreadCount + ''
      })
     } else {
      uni.removeTabBarBadge({
       index: 1
      })
     }
     return;
    } else { //聊天页面
        console.log('聊天',that.config.isChat,result.data);
     //接收对方发送过来的消息  发送者id == 接收者id
        if(result.data.userId == that.config.userId) {
      console.log(result.data);
      uni.$emit('updateMsg', result.data);
     }
    }
   });
  })
  
  // 链接开启后登录验证
  that.config.socketTask.onError((errMsg) => {
   console.log(errMsg)
   console.log("ws连接异常")
   this.webSocketClose(that);
  });
  
  // 链接开启后登录验证
  that.config.socketTask.onClose((errMsg) => {
   console.log(errMsg)
   console.log("ws连接关闭")
   this.webSocketClose(that);
  });
  
 },
 
 // 断开连接时
 webSocketClose(that, webSocketIsReconnect = true) {
  if(!webSocketIsReconnect) { //不重连
      console.log('断开连接');
   that.config.webSocketIsReconnect = false;
   that.config.socketTask.close();
  }
  // 修改状态为未连接
  that.config.webSocketIsOpen = false;
  that.config.socketTask = null;
  // 判断是否重连
  if (
   that.config.webSocketIsReconnect &&
   that.config.webSocketReconnectCount === 0
  ) {
   // 第一次直接尝试重连
   return;
   this.webSocketReconnect(that);
  }
 },
 
 // 定时心跳
 webSocketPing(that) {
  that.config.webSocketPingTimer = setTimeout(() => {
   if (!that.config.webSocketIsOpen) {
    return false;
   }
   console.log("心跳");
 //   const payload = {
 
 //    type: 0
 
 //   };
   // this.webSocketSend("11");
   clearTimeout(that.config.webSocketPingTimer);
   // 重新执行
   this.webSocketPing(that);
  }, this.config.webSocketPingTime);
 
 },
 
 // WebSocket 重连
 webSocketReconnect(that) {
  if (that.config.webSocketIsOpen) {
   return false;
  }
  console.log("第"+that.webSocketReconnectCount+"次重连")
  that.webSocketReconnectCount += 1;
  // 判断是否到了最大重连次数 
  // if (this.webSocketReconnectCount >= 10) {
  //  this.webSocketWarningText = "重连次数超限";
  //     return false;
  // }
  // 初始化
  console.log("开始重连")
  this.webSocketInit(that.config.url,that);
  // 每过 5 秒尝试一次,检查是否连接成功,直到超过最大重连次数
  let timer = setTimeout(() => {
   this.webSocketReconnect(that);
   clearTimeout(timer);
  }, 5000);
 },
 
 // 发送ws消息
 webSocketSend(sendContent, accessoryPath, that) {
  let now = new Date();
  now = dayjs(now).format('YYYY-MM-DD HH:mm:ss');
  return new Promise((resolve,reject)=> {
   http.post('chat/talk/push',{
    token: that.config.token,
    userId: that.config.senderId, //发送者
    contactId: that.config.userId, //接收者
    sendTime: now, //发送时间
    sendContent: sendContent, //发送内容
    accessoryPath: accessoryPath
   }).then(([err,res])=> {
    if(res.data.code == 200) {
     console.log('msg',res.data.data);
     this.msg = res.data.data;
     resolve(this.msg);
     // this.that.$store.commit('setChatRecordMsg', Object.assign({}, this.msg));
    } else {
     uni.showToast({
      title: res.data.msg, icon: 'none'
     })
     reject(res.data.msg)
    }
   }).catch(e=> {
   console.warning(e); 
   })
  })
 }
}
Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐