小程序使用socket.io

环境

服务端:Egg

  • egg2.15.1
  • egg-socket.io4.1.6

客户端:小程序

问题

1.小程序不支持socket.io

推荐使用weapp.socket.io

2.小程序端socket配置
// weapp.socket.io项目打包后的文件
const io = require('../static/js/weapp.socket.io');
io(url, {
    transports: ['websocket'], // 此项必须设置
});
3.服务端配置

Egg官方文档–sockit.io

4.服务端namespace理解
  • namespace的键需要和路由配置中io.of后面保持一致

    config.io = {
        // namespace命名空间配置为
        namespace: {
          '/api': {
            // 预处理器中间件, 我们这里配置了一个auth, 进行权限判断, 它对应的文件是/app/io/middleware/auth.js, 这里可以配置多个文件, 用逗号隔开
            connectionMiddleware: [ 'auth' ], // 这里我们可以做一些权限校验之类的操作
            packetMiddleware: [], // 通常用于对消息做预处理,又或者是对加密消息的解密等操作
          },
        },
      };
    
    io.of('/api').route('connect', io.controller.home.connect);
    
  • namespace的键需要与客户端建立连接的url的路径部分一样(端口后面,不包含查询)

    config.io = {
        // namespace命名空间配置为
        namespace: {
          '/api': {
            // 预处理器中间件, 我们这里配置了一个auth, 进行权限判断, 它对应的文件是/app/io/middleware/auth.js, 这里可以配置多个文件, 用逗号隔开
            connectionMiddleware: [ 'auth' ], // 这里我们可以做一些权限校验之类的操作
            packetMiddleware: [], // 通常用于对消息做预处理,又或者是对加密消息的解密等操作
          },
        },
      };
    
    const io = require('../static/js/weapp.socket.io');
    io('http://localhost:8080/api', {
        transports: ['websocket'], // 此项必须设置
    });
    
5.服务端io的路由配置中的route第一个参数
io.of('/api').route('connect', io.controller.home.connect);
io.of('/api').route('updatelist', io.controller.home.updatelist);
  • connect是sockte.io的自有事件(建立连接),还有disconnect(断开连接)等
  • 客户端自定义的事件updatelist,服务端要对应的修改route第一个参数updatelist
6.sockte.io客户端请求路径
io('http://localhost:8080/api', {
    transports: ['websocket'], // 此项必须设置
});
  • 请求路径是http://localhost:8080/socket.io,io会自动截取url并修改
  • 配置中url的路径部分/api,需要服务端config的io中namespace配置,并且路由中io.of参数保持一致

特殊情况

当egg服务端被Nginx代理出带有路径时,需要特殊处理,例如:请求路径需要变成http://localhost:8080/dev/socket.io

Nginx

location ^~/dev/socket.io {
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_pass http://localhost:8080/socket.io;
}

sockte.io客户端

io('http://localhost:8080/api', {
    path: '/dev/socket.io',
    transports: ['websocket'], // 此项必须设置
});

上面的io第一参数url一定不要写成http://localhost:8080/dev/api,写成这样会造成服务端的namespace不匹配,看ws消息可以知道会变成/dev/api,之前是/api

7.sockte.io客户端请求配置自定义请求头等
io('http://localhost:8080/api', {
    path: '/dev/socket.io',
    transports: ['websocket'], // 此项必须设置
    extraHeaders: {
      token: wx.getStorageSync(TOKEN), // header增加了token
    },
    reconnectionAttempts: 3, // 失败后重新连接次数,一直失败总共尝试四次
    reconnectionDelay: 2000, // 重新连接间隔时间毫秒
});
8.小程序端关闭和建立连接(个人理解)
  • 变量clientSocket存储socket.io用于不同生命周期操作
  • onShow建立连接并且赋值给clientSocket,监听权限事件,成功进行下一步操作,失败断开连接
  • onHide,onUnload进行断开连接操作,断开连接操作时需要判断是否存在clientSocket,并且clientSocket.connected为true
  • 监听error事件,关闭连接
9.服务端controller定时器轮询接口,清除定时器时机
  • 定时器变量timer不要挂载在this上面,挂载在this上面没效果
  • disconnect和connect时都清除定时器
  • 先请求一次接口(防止页面更新慢),成功后再进入轮询定时器
  • 接口报错时,清除定时器(否则会一直轮询)
  • 错误中间件不会捕获到定时器中的异常,这里要特别注意,可以尝试在请求方法中判断或者可以在定时器内部写try catch处理,用try catch包裹定时器也无法捕获到错误
10.服务端请求接口无响应

小程序请求过来的请求头直接透传给接口,由于小程序请求egg是websocket所以有握手环节的协议升级

Connection: Upgrade
Upgrade: websocket

但是接口不支持websocket协议,因此握手环节就失败,更不会返回结果,处理是把这两个请求头去掉。

11.客户端建立多个websocket连接

socket.io默认只会建立一个连接,前一个执行的很可能不会触发(监听)收消息回调。此时需要配置forceNew: true

io('http://localhost:8080/api', {
    path: '/dev/socket.io',
    transports: ['websocket'], // 此项必须设置
    extraHeaders: {
      token: wx.getStorageSync(TOKEN), // header增加了token
    },
    reconnectionAttempts: 3, // 失败后重新连接次数,一直失败总共尝试四次
    reconnectionDelay: 2000, // 重新连接间隔时间毫秒
    forceNew: true,
});
12.断开真机调试后无法连接websocket

开发工具模拟器、真机调试、断开真机之后打开调试都可以连接websocket,原因是没有配置socket安全域名。小程序遇到未知报错可以使用下面代码查看

 wx.onError(err => {
      wx.showModal({
        title: 'err',
        content: err
      })
 })
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值