基本思路是:
- 全局维护一个SocketTask对象,用来表示websocket连接,判断是否断线,作为重连的依据。
- 同时定义一个全局callback回调函数,每个页面初始化的时候更新这个回调函数,那么在每个页面中收到返回消息就会执行当前页面逻辑。
- 维护一个消息队列,所有消息请求会首先判断连接是否可用,如果可用直接发消息,否则将消息push到这个队列中。
- 在app.js的onShow()函数中判断连接是否连上,如果没有连上就会触发websocket连接
- SocketTask对象的onOpen()负责从消息队列中取出请求消息,并发送这个请求消息
- SocketTask对象的onMessage()负责接收返回消息,并调用每个页面自己定义的回调函数
- 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