小程序之websocket的使用

最近工作中需要实现在小程序中的玩家对战功能,因此需要使用websocket来实现用户之间的数据传递和实时对战功能。随笔主要记录自己工作中使用websocket遇到的问题和解决方法。

onSocketMessage使用

wepy.page创建的当前页面中通过使用onSocketMessage来对服务端socket的返回进行监听,但当我在另一个页面中通过sendSocketMessage发送数据时发现,原先运行后的onSocketMessage监听一直存在,并不会随着页面的跳转消失。如:

// 页面一
wepy.onSocketMessage(function(res) {
  console.log('组件收到内容:' + res.data)
})
// 页面二
wepy.sendSocketMessage(function(res) {
  data: JSON.stringify(data)          // data为传送的数据
})

测试发现当页面跳转到页面二进行触发的时候,页面一的监听结果打印出来了。即在开发不同的页面时,需要在当前页面写onSocketMessage来进行监听,覆盖之前其他页面中的onSocketMessage(一般性当前页面用到sendSocketMessage自然也会用到onSocketMessage,所以也不会存在什么问题)。但当onSocketMessageSocketTask进行混合使用的时候就需要小心了。

SocketTask

SocketTask即WebSocket 任务,可通过wepy.connectSocket()接口创建返回,如:

// 创建SocketTask
let SocketTask= wepy.connectSocket({
      url: 'ws://localhost:8181'',
      header: {
        'origin': '',
        'content-type': 'application/json'
      },
      method: 'GET',
      success () {
        console.log('连接成功')
      }
})

这样创建的SocketTask基本可以替换小程序中的wepy.connectSocket这一类的使用。但SocketTask的使用存在一个问题,即它是动态绑定的,有点像jQuery中的on绑定,会出现累计绑定。当我在页面的onLoad中直接书写时,如:

socketTask.onMessage((res) => {
      console.log(111)
})

测试打印结果发现,当页面多次运行的时候(不是重新编译),打印次数累加了,第一次打印一次,第二次打印两次......没有出现每次打印一次的效果。最后我就动态的在全局下扩展了一个变量来判断,只要小程序不重启,变量就不会清除,修改代码如下:

let friendGameMath = this.$parent.globalData.friendGameMath
if (!friendGameMath) {
    this.$parent.globalData.friendGameMath = 1
    socketTask.onMessage((res) => {
          console.log(111)
     })
}

测试发现终于多次运行也只打印一次了。

在使用sendSocketMessage发送指令的时候,一定要将发送指令发在onSocketOpen的回调函数中,不然运行会报错,提示websocket未连接wepy.onMessage最好写在onShow中,onLoad这个生命周期在页面返回的时候不会触发,可能导致写在当前页面的websocket不会开启监听,一直沿用之前的。socketTask在socket断开后会重新创建,所以在断开以后需要对之前扩展的变量初始化。不然重连后之前的绑定会失效。

onSocketMessage和socketTask的混合使用

在我们通过wepy.page创建页面时,考虑页面的复杂性,有时会将页面进行组件化。在不同的组件中使用websocket时,由于一个页面只能有一个onSocketMessage,当在不同的组件中使用onSocketMessage时,只会有一个生效,所以一般的方法就是在页面主体部分进行数据监听再通过父子组件通信或wepy-redux来实现这一类的功能。但如果组件中的内容都是通过websocket来传递数据的话,我觉得可以考虑使用onSocketMessagesocketTask的混合使用来实现。如下

// 主体
export default class PlayGame extends wepy.page{
      ....
      onLoad () {
          wepy.onSocketMessage((res) => {
              console.log(1111)
          }
      }
      ....
}
// 组件
export default class PlayGame extends wepy.component{
      ....
      onLoad () {
          let friendGameMath = this.$parent.globalData.friendGameMath
          if (!friendGameMath) {
                this.$parent.globalData.friendGameMath = 1
                socketTask.onMessage((res) => {
                      console.log(2222)
                })
           }
      }
      ....
}

这样就可以在主体和组件中都启动一个socket监听,来负责各自的业务逻辑和页面效果,不需要通过父子通信或wepy-redux来进行组件之间的传值了。

websocket重连

如果希望websocket连接一直保持,我们会在close或者error上绑定重新连接方法。

// 重连函数reconnect
ws.onclose = function () {
    reconnect();
};
ws.onerror = function () {
    reconnect();
};

我们可以在每一个组件中使用上述方式进行监听连接是否断开,在重新建立连接。但每个页面组件中都设置相同的代码会导致代码的臃肿且后期不好更改。所以考虑只需要实现监听连接是否断开,决定将这部分相同部分写在wepy的Mixin混合中,在app.wepy中导入一次即可。
在mixin中的代码如下:

wepy.onSocketClose((res) => {
      console.log('websocket关闭')
      this.globalData.socketOpen = false
})
wepy.onSocketOpen((res) => {
      console.log('WebSocket连接已打开!')
      this.globalData.socketOpen = true
 })

心跳包:

pdSocketOpen (data) {
    if (this.$parent.globalData.socketOpen) {
      wepy.sendSocketMessage({
        data: JSON.stringify(data),
        success: () => {
          console.log('getGameView:success')
        }
      })
      return
    }
    setTimeout(() => {
      this.pdSocketOpen(data)
    }, 633)
  }

通过在监听页面全局变量中boolean值,实现页面socket的重新连接和发送消息。

小程序服务端模拟

服务端采用的express框架和ws模块,在服务端启动websocket

var express = require('express');
var app = express();
var ws = require('ws').Server;
var wss = new ws({port: 8181});      // 小程序 connectSocket的url地址
// 模拟数据
var subjects = [{
    cmd: 'reqq',
    title: 'aaa',
    matter: 'asdasfasdasd',
    result: ['新西兰', '加拿大', '巴西', '澳大利亚'],
    trueRes: '澳大利亚'
}]
wss.on('connection', function (ws) {
    console.log('client connected')
    ws.on('message', function (message) {
        let obj = JSON.parse(message)
        if (obj.cmd == 'excans') {
            wss.clients.forEach(function (client) {        // wss.clients表示连接的所有客户端socket
                let data = JSON.stringify(obj)
                client.send(data)
            })
        } else if (obj.cmd == 'reqq') {
            let index = obj.index
            wss.clients.forEach(function (client) {
                let data = JSON.stringify(subjects[index])
                client.send(data)
            })
        }
    })
})

app.listen(3000, function () {
    console.log('listen 3000')
})

以上皆为个人观点,如有错误,请大家指正。
微信小程序中的websocket参考文档: https://developers.weixin.qq.com/miniprogram/dev/api/network-socket.html

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,753评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,668评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,090评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,010评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,054评论 6 395
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,806评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,484评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,380评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,873评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,021评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,158评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,838评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,499评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,044评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,159评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,449评论 3 374
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,136评论 2 356

推荐阅读更多精彩内容

  • title: 小程序教程之wepy 参考文档 中文文档:https://tencent.github.io/wep...
    采香行处蹙连钱阅读 11,941评论 8 24
  • (清晨,宝儿伸了一个长长的懒腰,紧接着一通“佛山无影脚”上下乱踹,屏息,睁眼,醒来……) 宝爸:臭宝醒了呀! 宝儿...
    迪吉卡阅读 234评论 0 1
  • 斗转星移,岁月的影子在星空下徘徊;人生如梦,匆匆的行者在人生的左岸游走。我们揉了揉惺忪的睡眼,还来不及打探一下周围...
    忍远阅读 425评论 0 1
  • 高铭玉阅读 171评论 0 0