【uniapp】多websocket场景下通过uni.onSocketMessage监听websocket消息遇到的问题

1,500 阅读2分钟

前言

对以下两种sdk进行简单介绍

  1. im sdk:该 sdk 提供单人、多人的多场景通讯能力,为社交软件提供底层逻辑
  2. webAT sdk:该 sdk 用于 im sdk 的自动化测试。webAT sdk 会先建立 websocket 连接,等待服务端的测试指令,之后调用 im sdk 进行一系列 api 测试。

背景

将 uniapp 测试 demo 运行在浏览器环境时,webAT sdk websocket 可以正常通信,im sdk 建立了 websocket 连接,服务器下发了 connet 命令,但是浏览器端 socket 并没有真正收到 connet 命令,反而是收到了 webAT sdk 下发的 socket 消息。即出现了 A 和 B (浏览器端) socket 都收到了 A (服务端) socket 的消息这一奇异现象。

WeChat65c9f6aef73f592f633f4dcce6ab7208.jpg

webAT sdk 建立的 websocket 连接

WechatIMG203.png

im sdk 建立的 websocket 连接

WechatIMG202.png

im sdk 收到了 webAT sdk 的消息

为什么使用全局方法监听?

因为支付宝小程序的 socketTask 的 onMessage 回调参数的数据结构,和微信、抖音和百度小程序的数据结构不一致。微信、抖音和百度的 data 在 event.data 中,而 ali 的 data 在 event.data.data 里面。 由于不确定将来的版本 onMessage 返回的数据会不会变更,所以当时采用全局方法 uni.onSocketMessage 监听 socket 消息。

解决方案

修改前使用全局方法监听 websocket 的 open、error、close 和 message 方法

uni.connectSocket({
  url: 'xxx',
  ...connectParams,
  fail: (event) => {
    // ...
  }
})

uni.onSocketOpen((event) => {
  // ...
})

uni.onSocketError((event) => {
  // ...
})

uni.onSocketClose((event) => {
  // ...
})

uni.onSocketMessage((event) => {
  // ...
})

// ...

function send(data) {
  // ...
  uni.sendSocketMessage({ data })
}

function close(){
  // ...
  uni.closeSocket({
      code: 'xxx',
      reason: 'xxx',
      complete: () => {}
  })
}

修改后使用 socketTask 对象监听 websocket 的 open、error、close 和 message 方法

this.socketTask = uni.connectSocket({
  url: 'xxx',
  ...connectParams,
  fail: (event) => {
    // ...
  }
})

this.socketTask.onOpen((event) => {
  // ...
})

this.socketTask.onError((event) => {
  // ....
})

this.socketTask.onClose((event) => {
  // ...
})

this.socketTask.onMessage((event) => {
 let data
 // 微信、抖音和百度的 data 在 event.data 中,阿里的 在 event.data.data 中
 // 需要通过某种手段区分阿里和其他小程序
 if (typeof event.data === 'string') {
     data = event.data
 } else {
     data = event.data.data
 }
 // ...  
})

// ...

function send(data) {
  // ...
  this.socketTask.send({ data })
}

function close(){
  // ...
  this.socketTask.close({
      code: 'xxx',
      reason: 'xxx',
      complete: () => {}
  })
}

最后

uniapp 参考文档