用websocket实现网页微聊功能

首先对chat和chatwindow布局之后
使用websocket的步骤
在chartwindow里面引入wsclient文件夹
建立聊天的步骤
1,注册,在componentdidmount里面
 //聊天第一步:注册用户
    const uid=localStorage.getItem('uid')
    let client=handle(uid,data=>{
        this.reseMsg(data)
    })
    this.setState({
        client//这个要在constuctor里面的state里面声明,相当于保存信息
    })
2,发送信息
 sendMsg = () => {
      //设置消息格式和内容
    let {to_user,from_user,avatar}=this.props.item
    let {list,client,msgContent}=this.state
    //封装消息数据包
    let pdata = {
        id: Math.random() + '',
        from_user: from_user,
        to_user: to_user,
        avatar: avatar,
        chat_msg: msgContent
      }
      //聊天第二步,发送消息
      client.emitEvent(IMEvent.MSG_TEXT_SEND, JSON.stringify(pdata))
      //处理页面
      let temp=list
      temp.push(pdata)
      this.setState({
          list:temp,
          msgContent:''状态-输入框里面的内容,发送之后清空输入框
      })
  }

  //聊天第三步,接收信息,这段代码应该放到 1中的this.reseMsg(data)的
  reseMsg=data=>{
      if(data.content==='对方不在线'){
          return
      }
      let temp=this.state.list
      temp.push(JSON.parse(data.content))
      this.setState({
          list:temp
      })
  }

wsclient.js代码
const config = {
  wsBaseUrl: 'ws://47.96.21.88:8087'
}
// 消息数据包格式
class DataPacket {
  constructor(message) {
    // 消息格式转化为对象
    if (typeof message === 'string') {
      try {
        this._data = JSON.parse(message)
      } catch (error) {
        this._data = undefined
      }
    } else if (typeof message === 'object') {
      this._data = message
    }
  }

  get data() {
    return this._data
  }

  get content() {
    return this._data['content']
  }

  get type() {
    return this._data['type']
  }

  set type(type) {
    this._data['type'] = type
  }

  get rawMessage() {
    return JSON.stringify(this._data)
  }
}

// 消息名称常量
const IMEvent = {
  CONNECTED: 'connected', // 已连接
  DISCONNECTED: 'disconnected', // 断开连接
  MSG_TEXT_SEND: 'msg_text_send', // 发送消息
  MSG_TEXT_REC: 'msg_text_rec', // 接收消息
  USER_REG: 'user_reg' // 用户注册
}

// Websocket通信基础功能封装
class IMClient {
  constructor(url) {
    // Websocket连接地址
    this._url = url
    // 自定义事件存储对象
    this._handlers = {}
    // 连接状态位
    this._isOpened = false
    // socket实例对象
    this._socket = null

    // 添加链接监听
    this.addEventListener(IMEvent.CONNECTED, () => {
      this._isOpened = true
    })

    // 添加断开监听
    this.addEventListener(IMEvent.DISCONNECTED, () => {
      this._isOpened = false
    })
  }

  // 连接
  connect() {
    if (!this._socket) {
      this._socket = new WebSocket(this._url)
      this._socket.onmessage = evt => {
        this.onMessage(evt.data)
      }
      this._socket.onopen = ws => {
        this.onOpen(ws)
      }
      this._socket.onclose = ws => {
        this.onClose(ws)
      }
      this._socket.onerror = ws => {
        this.onError(ws)
      }
    }
  }

  // 消息接收
  onMessage(message) {
    if (typeof message === 'string') {
      this.dispatchMessage(message)
    }
  }

  // 打开回调
  onOpen() {
    this.emitEvent(IMEvent.CONNECTED)
  }

  // 关闭回调
  onClose() {
    this._socket = undefined
    this.emitEvent(IMEvent.DISCONNECTED)
  }

  // 出现错误回调
  onError() {
    this._socket = undefined
  }

  // 向服务器发送数据包
  sendDataPacket(dataPacket) {
    if (this._isOpened) {
      this._socket.send(dataPacket.rawMessage)
    }
  }

  /**
   * 发射事件
   * @param {string} type 事件类型
   * @param {参数列表} args 传递事件参数
   */
  emitEvent(type, ...args) {
    if (this._handlers[type] && this._handlers[type].length > 0) {
      let handlers = this._handlers[type]
      for (var i = 0; i < handlers.length; i++) {
        handlers[i].call(this, ...args)
      }
    }
  }

  /**
   * 添加事件监听
   * @param {string} type 事件类型
   * @param {Function} callback 事件处理函数
   */
  addEventListener(type, handler) {
    if (!this._handlers[type]) {
      this._handlers[type] = []
    }
    this._handlers[type].push(handler)
  }

  /**
   * 移除事件
   * @param {string} type 事件类型
   * @param {*} callback
   */
  removeEventListener(type, handler) {
    if (this._handlers[type] && this._handlers[type].length > 0) {
      let handlers = this._handlers[type]
      for (var i = handlers.length - 1; i >= 0; i--) {
        if (handler === handlers[i]) {
          handlers.splice(i, 1)
        }
      }
    }
  }

  /**
   * 消息封装成数据包
   */
  dispatchMessage(message) {
    let dataPacket = new DataPacket(message)
    if (dataPacket.data) {
      this.dispatchDataPacket(dataPacket)
    }
  }

  /**
   * 处理数据包
   */
  dispatchDataPacket(dataPacket) {
    this.emitEvent(dataPacket.type, dataPacket)
  }
}

// 实际消息处理功能
const handle = (currentUser, handleMsg) => {
  // 创建Websocket客户端
  const client = new IMClient(config.wsBaseUrl)

  // 注册身份
  client.addEventListener(IMEvent.CONNECTED, () => {
    // 创建消息数据包
    let dataPacket = new DataPacket({
      type: IMEvent.USER_REG,
      content: currentUser
    })
    client.sendDataPacket(dataPacket)
  })

  // 发送消息
  client.addEventListener(IMEvent.MSG_TEXT_SEND, data => {
    // 创建消息数据包
    let dataPacket = new DataPacket({
      type: IMEvent.MSG_TEXT_SEND,
      content: data
    })
    client.sendDataPacket(dataPacket)
  })

  // 接收消息
  client.addEventListener(IMEvent.MSG_TEXT_REC, data => {
    handleMsg(data)
  })

  // 连接Websocket
  client.connect()
  return client
}

export { IMEvent }
export default handle
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值