封装小程序的websocket

摘要:这两天的工作中,我重构了一个项目里的客服聊天功能,是小程序的,用了小程序提供的websocket有关的接口,我感觉很简单,和web端的接口大体一致,不过我喜欢封装后去使用,封装成一个类,创建一个类的实例

这两天的工作中,我重构了一个项目里的客服聊天功能,是小程序的,用了小程序提供的websocket有关的接口,我感觉很简单,和web端的接口大体一致,不过我喜欢封装后去使用,封装成一个类,创建一个类的实例,通过这个实例上的方法去调用方法,去监听返回的消息,同时发送消息,我觉得这样会比较方便。

/**
 * 返回一个布尔值判断传入的url是否为WSS开头的链接
 * @param {String} url 需要判断的URL
 */
function isAbsoluteWss(url) {
  return /^(wss:\/\/).*/.test(url)
}

export default class Socket {
  /** 链接的URL */
  url = ''
  /** 是否链接成功的状态 */
  socketOpenStatus = false
  /** 实例 */
  websocket = null
  /** 消息队列 */
  socketMsgQueue = []
  /** 消息监听的函数 */
  fn = null

  /**
   *
   * @param {String} url websocket的链接地址
   * @param {Function} fn 消息监听事件
   */
  constructor(url, fn) {
    if (!url)
      throw new Error('websocket的链接URL不能为空')

    if (!isAbsoluteWss(url))
      throw new Error(`websocket的链接${url}必须是以 wss:// 开头`)

    this.url = url
    this.fn = fn
  }

  /** 链接websocket */
  connect() {
    this.websocket = wx.connectSocket({
      url: this.url
    })

    // 监听websocket链接打开
    this.websocket.onOpen((data) => {
      this.socketOpenStatus = true
      // 初始化监听事件
      this.initHandleMonitor()
      if (this.fn) {
        this.fn({
          type: 'open',
          data
        })
      }

      // 如果消息队列里有消息
      if (this.socketMsgQueue.length) {
        this.socketMsgQueue.forEach(item => item())
      }

      this.socketMsgQueue = []
    })
  }

  /** 发送消息 */
  send(data) {
    if (data !== null && typeof data === 'object') {
      data = JSON.stringify(data)
    }

    // 判断当前的链接是否链接成功
    if (this.socketOpenStatus) {
      this.websocket.send({
        data
      })
    } else {
      this.socketMsgQueue.push(() => {
        this.websocket.send({
          data
        })
      })
    }
  }

  /** 监听消息的绑定 */
  initHandleMonitor() {

    /** 消息的回调 */
    this.websocket.onMessage(res => {
      const data = JSON.parse(res.data)
      if (this.fn) {
        this.fn({
          type: 'message',
          data
        })
      }
    })

    /** 报错的回调 */
    this.websocket.onError(res => {
      this.socketOpenStatus = false

      if (this.fn) {
        this.fn({
          type: 'error',
          data: res.errMsg
        })
      }
    })

    /** 关闭的回调 */
    this.websocket.onClose(data => {
      this.socketOpenStatus = false

      if (this.fn) {
        this.fn({
          type: 'close',
          data
        })
      }
    })
  }

  /** 关闭websocket链接 */
  close(code, reason) {
    if (this.socketOpenStatus) {
      this.socketOpenStatus = false
      this.websocket.close({
        code,
        reason
      })
    }
  }

  /** 返回是否链接成功 */
  isOpen() {
    return this.socketOpenStatus
  }
}
上面是我封装的代码,使用了es6的类,创建一个类,在创建的同时,传入websocket的链接地址,通过第二个参数中的回调函数实现消息的返回监听。第一个方法是判断传入的连接链接是否有效,只是一个简单的判断,只判断传入的参数是否符合wss://开头,后续需要修改完善。
我在类中写了initHandleMonitor这个方法,是因为事件的绑定函数,需要在websocket链接成功后,并返回了这个实例,才能在实例上绑定,所以我选择在websocket链接成功后绑定,并执行websocket未链接成功前,已经发送的命令。返回的消息,返回一个对象,对象中有两个属性,一个为type是消息的类型,一个是data是websocket中发的消息。
send方法中,通过判断当前传入的消息体的数据类型,如果是非字符串,则使用JSON.stringify()来JSON格式化消息体,因为小程序的data只能发送字符串string和ArrayBuffer。send在每一次发送消息前会去判断websocket是否已经构建成功。


本文内容仅供个人学习、研究或参考使用,不构成任何形式的决策建议、专业指导或法律依据。未经授权,禁止任何单位或个人以商业售卖、虚假宣传、侵权传播等非学习研究目的使用本文内容。如需分享或转载,请保留原文来源信息,不得篡改、删减内容或侵犯相关权益。感谢您的理解与支持!

链接: https://shenqiku.cn/article/FLY_5074