内容简介:微信基础库1.7.0之后的版本提供了新版的WebSocket API,考虑到兼容性问题,尝试整合新旧两种版本的API,进行简单的封装。从以下几个角度对微信小程序中所提供的WebSocket API封装支持1.7.0+,连接后会返回一个SocketTask对象,在该对象上监听该连接的各种事件与执行发送消息等操作。
微信基础库1.7.0之后的版本提供了新版的WebSocket API,考虑到兼容性问题,尝试整合新旧两种版本的API,进行简单的封装。
从以下几个角度对微信小程序中所提供的WebSocket API封装
- API兼容性
- 重连机制
小程序WebSocket API
旧版WebSocket API的使用
- 创建 - wx.connectSocket
- 发送消息 - sendSocketMessage
- 监听事件 - onSocketOpen
let socketOpen = false const socketMsgQueue = [] // 连接socket wx.connectSocket({ url: 'test.php' }) // 监听打开事件 wx.onSocketOpen(function(res) { socketOpen = true for (let i = 0; i < socketMsgQueue.length; i++){ sendSocketMessage(socketMsgQueue[i]) } socketMsgQueue = [] }) // 发送消息 function sendSocketMessage(msg) { if (socketOpen) { wx.sendSocketMessage({ data:msg }) } else { socketMsgQueue.push(msg) } }
新版WebSocket API的使用
支持1.7.0+,连接后会返回一个SocketTask对象,在该对象上监听该连接的各种事件与执行发送消息等操作。
let socketTask = wx.connectSocket({ url: 'test.php' }) // 监听打开事件 socketTask.onOpen(function(res) { socketOpen = true // 发送信息 socketTask.send({msg: "hello world"}) })
并发数
-
1.7.0
及以上版本,最多可以同时存在5
个WebSocket
连接。 -
1.7.0
以下版本,一个小程序同时只能有一个WebSocket
连接,如果当前已存在一个 WebSocket 连接,会自动关闭该连接,并重新创建一个WebSocket
连接。
模块封装
简单封装封装一个兼容新旧socketAPI的模块,仅考虑存在单个socket连接的情况
创建与事件监听
- 新版: 在socket连接时会返回一个socketTask对象,监听事件是在该对象的基础上进行
- 旧版: 直接使用wx放进行创建与监听方法
统一创建与添加监听函数
init() { let st = this.connect() this.listen(st) this.manualClose = false }
创建连接
connect() { let st = wx.connectSocket(this.config.server) return st }
添加事件监听函数
listen(st) { if (st !== undefined) { this.ws = st this.ws.onOpen(() => this.openHandle()) this.ws.onError(() => this.errorHandle()) this.ws.onClose(() => this.closeHandle()) this.ws.onMessage(res => this.messageHandle(res)) } else { wx.onSocketOpen(() => this.openHandle()) wx.onSocketError(() => this.errorHandle()) wx.onSocketClose(() => this.closeHandle()) wx.onSocketMessage(res => this.messageHandle(res)) } }
重连机制
预设标记位
retryLock = false; // 避免多次同时重连 socketOpen = false; // 连接状态 manualClose = false; // 主动断开标记
在连接关闭监听函数中执行重连
closeHandle() { console.info('WebSocket closed') this.socketOpen = false this.retryLock = false // 不论是error还是close都会触发close事件,统一在这里进行重连 // 初次连接失败不进行重连(失败不会进入到onOpen的监听事件中,那时未声明retryTimes变量) this.retryTimes !== undefined && this.reconnect() }
判断重连锁与是否主动断开进行重连
reconnect() { if (this.retryLock) return this.retryLock = true // 若manualClose为true,表明不是主动断开 if (!this.manualClose) { // 开始重连 setTimeout(() => { this.retry() }, this.retryInterval) } }
重连函数,包含重连次数的限制
retry() { if ( this.socketOpen || (this.retryTimes > 0 && this.retryCount <= this.retryTimes) ) { console.warn(`reconnect ending. reconnect ${this.retryTimes} times`) if (!this.socketOpen) { this.config.closeCallback() } return } this.retryTimes += 1 console.warn(`[ ${this.retryTimes} ]th reconnect WebSocket...`) this.init() }
消息队列
添加消息队列,当重连后自动发送缓存消息
openHandle() { this.retryTimes = 0 this.socketOpen = true this.retryLock = false this.messageQueue.map(e => this.send(e)) this.messageQueue = [] }
若发送时断开则先将消息缓存到消息队列中
send(value) { let data = this.msgWrapper(value) data = JSON.stringify(data) if (!this.socketOpen) { this.messageQueue.push(data) } else { if (this.ws) { this.ws.send({ data }) } else { wx.sendSocketMessage({ data }) } } }
辅助函数
添加一些包裹消息格式的 工具 函数
messageIndex = 0; helper = { isPlainObject: val => Object.prototype.toString.call(val) === '[object Object]', nextId: () => { this.messageIndex += 1 return this.messageIndex }, id: () => Date.now() + '.' + this.helper.nextId() }; msgWrapper(data) { let msg = data if (this.helper.isPlainObject(msg)) { if (msg.type) { return msg } else { return this.msgWrapper({ type: 'message', msg, id: this.helper.id() }) } } else { return this.msgWrapper({ type: 'message', msg, id: this.helper.id() }) } }
完整代码
export default class WXWebSocket { messageQueue = []; // 消息队列 retryLock = false; // 避免多次同时重连 socketOpen = false; manualClose = false; // 主动断开标记 constructor(config) { this.config = config || {} // 重连间隔 this.retryInterval = this.config.retryInterval && this.config.retryInterval > 100 ? this.config.retryInterval : 3000 // 重连次数 this.retryCount = this.config.retryCount || 5 this.init() } init() { let st = this.connect() this.listen(st) this.manualClose = false } connect() { let st = wx.connectSocket(this.config.server) console.log('current socket: ', st) return st } listen(st) { // 添加监听事件 if (st !== undefined) { // 若存在SocketTask,则要通过readyState判断状态 // CONNECTING: 0 // OPEN: 1 // CLOSING: 2 // CLOSE: 3 this.ws = st this.ws.onOpen(() => this.openHandle()) this.ws.onError(() => this.errorHandle()) this.ws.onClose(() => this.closeHandle()) this.ws.onMessage(res => this.messageHandle(res)) } else { wx.onSocketOpen(() => this.openHandle()) wx.onSocketError(() => this.errorHandle()) wx.onSocketClose(() => this.closeHandle()) wx.onSocketMessage(res => this.messageHandle(res)) } } close() { this.manualClose = true if (this.ws) { this.ws.close() } else { wx.closeSocket() } } send(value) { console.log('send value: ', value) let data = this.msgWrapper(value) data = JSON.stringify(data) if (!this.socketOpen) { // add new message to queue this.messageQueue.push(data) } else { if (this.ws) { this.ws.send({ data }) } else { wx.sendSocketMessage({ data }) } } } openHandle() { console.info('WebSocket connected') this.retryTimes = 0 this.socketOpen = true this.retryLock = false this.messageQueue.map(e => this.send(e)) this.messageQueue = [] } errorHandle() { console.error('WebSocket error') this.socketOpen = false } closeHandle() { console.info('WebSocket closed') this.socketOpen = false this.retryLock = false // 不论是error还是close都会触发close事件,统一在这里进行重连 // 初次连接失败不进行重连(失败不会进入到onOpen的监听事件中,那时未声明retryTimes变量) this.retryTimes !== undefined && this.reconnect() } reconnect() { if (this.retryLock) return this.retryLock = true // 若manualClose为true,表明不是主动断开 if (!this.manualClose) { // 开始重连 setTimeout(() => { this.retry() }, this.retryInterval) } } retry() { if ( this.socketOpen || (this.retryTimes > 0 && this.retryCount <= this.retryTimes) ) { console.warn(`end reconnect. reconnect ${this.retryTimes} times`) if (!this.socketOpen) { this.config.closeCallback() } return } this.retryTimes += 1 console.warn(`[ ${this.retryTimes} ]th reconnect WebSocket...`) this.init() } messageHandle(res) { this.config.responseCallback(res) } msgWrapper(data) { let msg = data if (this.helper.isPlainObject(msg)) { if (msg.type) { return msg } else { return this.msgWrapper({ type: 'message', msg, id: this.helper.id() }) } } else { return this.msgWrapper({ type: 'message', msg, id: this.helper.id() }) } } messageIndex = 0; helper = { isPlainObject: val => Object.prototype.toString.call(val) === '[object Object]', nextId: () => { this.messageIndex += 1 return this.messageIndex }, id: () => Date.now() + '.' + this.helper.nextId() }; }
使用
创建连接
let socketTask = new WXWebSocket({ server: this.wsServerOption, responseCallback: e => { let { data } = e let { msg } = JSON.parse(data) this.msgStack.push(msg) }, closeCallback: () => { this.socketTask = null } }) this.socketTask = socketTask
发送消息
sendWSMessage(msg) { this.msgStack.push(msg) this.socketTask && this.socketTask.send(msg) },
关闭连接
closeWS() { if (!this.socketTask) return if (this.socketTask.socketOpen) { this.socketTask.close() this.socketTask = null } }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 小程序优化实践
- 小程序webview应用实践
- 编程日历小程序,对小程序云开发和生成海报的实践
- 给小程序再减重 30% 的秘密(京喜小程序首页瘦身实践)
- 程序员必备,“向上管理” 实践指南
- Clojure 并发实践:使用 pmap 加速程序
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
我看电商3:零售的变革
黄若 / 电子工业出版社 / 2018-4 / 49
在《我看电商3:零售的变革》之前,黄若先生的“我看电商”系列图书《我看电商》《再看电商》《我看电商2》,均为行业畅销书。黄若先生的图书有两大特如一是干货满满,二是观点鲜明。 “新零售”是眼下的热门词。在2017年里,数以万计的企业以“新零售”作为标识进入市场。但是社会上对“新零售“存在着各种模糊的定义和不尽相同的解读。 《我看电商3:零售的变革》中明确提出:新零售不应过分关注于渠道形式......一起来看看 《我看电商3:零售的变革》 这本书的介绍吧!