1. 程式人生 > >微信小程式使用 Websocket

微信小程式使用 Websocket

基本思路是:

  1. 全域性維護一個SocketTask物件,用來表示websocket連線,判斷是否斷線,作為重連的依據。
  2. 同時定義一個全域性callback回撥函式,每個頁面初始化的時候更新這個回撥函式,那麼在每個頁面中收到返回訊息就會執行當前頁面邏輯。
  3. 維護一個訊息佇列,所有訊息請求會首先判斷連線是否可用,如果可用直接發訊息,否則將訊息push到這個佇列中。
  4. 在app.js的onShow()函式中判斷連線是否連上,如果沒有連上就會觸發websocket連線
  5. SocketTask物件的onOpen()負責從訊息佇列中取出請求訊息,併發送這個請求訊息
  6. SocketTask物件的onMessage()負責接收返回訊息,並呼叫每個頁面自己定義的回撥函式
  7. SocketTask物件的onClose()監聽函式中,觸發websocket連線

下面是app.js程式碼:

let socketMsgQueue = []
let isLoading = false

App({
  globalData: {
    userInfo: null,
    localSocket: {},
    callback: function () {}
  },
  onLaunch: function (options) {
    // 展示本地儲存能力
    var logs = wx.getStorageSync('logs') || []
    logs.unshift(Date.now())
    wx.setStorageSync('logs', logs)
    const updateManager = wx.getUpdateManager()
    updateManager.onUpdateReady(function () {
      updateManager.applyUpdate()
    })
    let that = this
    
    // 登入
    wx.login({
      success: res => {
        // 傳送 res.code 到後臺換取 openId, sessionKey, unionId
      }
    })
    // 獲取使用者資訊
    wx.getSetting({
      success: res => {
        if (res.authSetting['scope.userInfo']) {
          // 已經授權,可以直接呼叫 getUserInfo 獲取頭像暱稱,不會彈框
          wx.getUserInfo({
            success: res => {
              // 可以將 res 傳送給後臺解碼出 unionId
              this.globalData.userInfo = res.userInfo
              // 由於 getUserInfo 是網路請求,可能會在 Page.onLoad 之後才返回
              // 所以此處加入回撥以防止這種情況
              if (this.userInfoReadyCallback) {
                this.userInfoReadyCallback(res)
              }
            }
          })
        }
      }
    })
  },
  showLoad() {
    if(!isLoading) {
      wx.showLoading({
        title: '請稍後...',
      })
      isLoading = true
    }
  },
  hideLoad() {
    wx.hideLoading()
    isLoading = false
  },
  initSocket() {
    let that = this
    that.globalData.localSocket = wx.connectSocket({
      // url: 'wss://test.enzhico.net/app'
      url: 'wss://mapp.enzhico.net/app'
    })
    that.showLoad()
    that.globalData.localSocket.onOpen(function (res) {
      console.log('WebSocket連線已開啟!readyState=' + that.globalData.localSocket.readyState)
      that.hideLoad()
      while (socketMsgQueue.length > 0) {
        var msg = socketMsgQueue.shift();
        that.sendSocketMessage(msg);
      }
    })
    that.globalData.localSocket.onMessage(function(res) {
      that.hideLoad()
      that.globalData.callback(res)
    })
    that.globalData.localSocket.onError(function(res) {
      console.log('readyState=' + that.globalData.localSocket.readyState)
    })
    that.globalData.localSocket.onClose(function (res) {
      console.log('WebSocket連線已關閉!readyState=' + that.globalData.localSocket.readyState)
      that.initSocket()
    })
  },
  //統一發送訊息
  sendSocketMessage: function (msg) {
    if (this.globalData.localSocket.readyState === 1) {
      this.showLoad()
      this.globalData.localSocket.send({
        data: JSON.stringify(msg)
      })
    } else {
      socketMsgQueue.push(msg)
    }
  },
  onShow: function(options) {
    if (this.globalData.localSocket.readyState !== 0 && this.globalData.localSocket.readyState !== 1) {
      console.log('開始嘗試連線WebSocket!readyState=' + this.globalData.localSocket.readyState)
      this.initSocket()
    }
  }
})

下面是某個頁面的onshow()函式:

onShow: function () {
  var that = this
  app.globalData.callback = function (res) {
    let resData = JSON.parse(res.data)
    let data = resData.result
    if (resData.method == 'list') {
      that.setData({
        total: parseInt(data.allAmount),
        amount: data.orderNum,
        jdcAmount: parseInt(data.jdcAmount),
        jszAmount: parseInt(data.jszAmount),
        list: data.list || []
      })
      if(data.list == 0) {
        that.setData({
          isEmpty: true
        })
      }
      that.getNumber(resData.result.allAmount)
      that.setAmount()
    } else if (resData.method == 'notify') {
      // 伺服器推送訊息,省略具體邏輯
    }
  }
  setTimeout(function () {
    app.sendSocketMessage({
      method: 'list'
    })
  }, 300)
},

https://www.xncoding.com/2017/12/15/weixin/ma-websocket.html