- 使用小程序WebSocket API功能,实现调试本地Websocket服务
小程序很早就提供了Websocket API功能,现在官方推荐的做法是使用SocketTask的方式去管理WebSocket链接,这样可以使每一条链路的生命周期更加可控。 小程序使用WebSocket功能,非常简单。 1,创建WebSocket 实例,使用wx.connectSocket。 var ws = null; ws = wx.connectSocket({ url: url, timeout: 3000, }) 2,设置监听。 ws.onError(that.wsErr) ws.onOpen(that.wsConn) ws.onMessage(that.wsMsg) ws.onClose(that.wsClose) 3,发送数据。 ws.send({ data: msg, success:()=>{ that.setData({ tips: "发送信息成功" }) } }) 4,关闭连接。 const that = this; if (!utils.isEmpty(ws)) { // console.log('ws close,', res) ws.close() ws = null; that.setData({ isConn: false, tips: "连接关闭" }) } 以上,是使用Websocket的一些核心代码,你可以根据你的业务需求加以完善。我的小程序实现了一个功能,使用小程序的Websocket API,可以调试局域网内的Websocket服务。这个功能,对于开发排查一些问题来说,非常有用。 调试界面如下: [图片] 对于一些使用设备服务,或者本地开发环境,可以作为Websocket调试客户端使用。
03-25 - (20)长连开发经验分享
在微信小程序/小游戏的开发中,网络传输主要是依靠http的短连接和webSocket 长连接来完成的。 在一般web服务中,大多使用短连接来向服务器请求资源,与服务器的交互频率低,次数少。而在一些需要与服务器交互频繁,需要及时收到服务器推送的场景,比如直播、多人实时游戏,更适合使用 webSocket 进行通讯。 这次的小故事主要分享 webSocket 在微信小程序/小游戏开发上的一些经验。 长连的生命周期介绍 webSocket的生命周期一共有4个状态:connecting、open、closing、closed。我们可以通过 socketTask 的 readyState 属性来获取当前 webSocket 长连的状态。webSocket 的生命周期过程和 API 间的调用关系可以简单的入下图所示。 [图片] 注意:只有长连处在 open 状态,才能够正常的收发消息,其他状态均会报错。 客户端长连的断开机制 当小游戏进入到后台运行超过5秒时,客户端会禁止小游戏的所有网络连接。这是一个非常频繁的断线逻辑,十分考验程序断线错误处理逻辑。建议大家可以在用户点击右上角按钮退出小程序/小游戏时,主动帮用户断线,待用户切回时再重接上去。 当 webSocket 长连超过一段时间没有任何网络传输时,客户端会主动关闭这条长连,以节省资源。开发者可以设置业务心跳,每隔一段时间与后台进行一次通讯,维持长连。 如何选择长连的接口 API接口主要有两类,一类是前缀为 “wx” 的接口,一类 “socketTask” 的接口。举例,同样是连接长连后发送一条消息,两种写法区别如下。 [图片] 最初小游戏只允许存在1个 webSocket 连接时,并没开放 socketTask 的管理方式。随着小游戏的能力提升,可支持同时存在的 webSocket 连接个数变多,在使用 wx.connectSocket 创建 webSocket 连接时会返回 socketTask 任务对象,便于去管理每一条连接链路。 推荐开发者尽量使用 socketTask 的方式去管理 webSocket 链接,每一条链路的生命周期都更加可控。同时存在多个 webSocket 的链接的情况下使用 wx 前缀的方法可能会带来一些和预期不一致的情况。例如:当存在多条连接时,wx.onSocketOpen、wx.sendSocketMessage、wx.onSocketMessage 等接口会只作用于第一条连接的长连。且wx.onSocketOpen 接口不能多次注册 webSocket 长连的回调函数,仅最后一次生效。使用 socketTask 任务的方式则不会出现上述问题。 开发与调试的建议 01微信提供了 webSocket 最基础的接口能力,开发者可以在其基础上进行封装,根据业务需要扩展能力。比如封装一个 offSocketOpen 的方法来取消注册 socketOpen 的回调函数。 02 长连并没有像短连那样“一问一答”的交互形式。在某些场景下,开发者需要这种与服务器的交互。建议前端与后台协议,每条客户端上行的信息,服务器都下发一个对应的回包,去“模拟短连”。比如开发者向服务器询问1+1和1+2等于多少,服务器返回了3和2,便可清晰知道哪一个数字对应着哪一个请求的答案。此外,还可以设置业务超时逻辑,便于判断上传是否丢包 03 在 webSocket 发送数据时,数据格式可以选择string或者ArrayBuffer。这里要注意的是,由于小游戏禁止了 Function() 和 eval()语法。所以像 protobufjs 这类用了这些语法的库是不能直接拿来用的。 04 在测试调试长连的时,目前开发者工具不支持通过设置 offline 模拟长连断网的情况(短连是支持的),所以在测试断线重连的一些情况时,可以辅助一些第三方工具,或者用真机调试以及“拔网线”的方式来测试。 05 在进行多人游戏测试时,在开发者工具中熟练使用“自定义编译条件”,以及“多账号调试”这两个功能可以极大的提升开发测试效率。 06 长连占用的系统资源,会导致手机发热比较明显。所以在不需要使用 webSocket 的场景下,建议及早断开长连,需要时再连接。 异常断线的监控 监控长连是否异常断线,在长连的使用中,尤其在小游戏多人对战中是尤为重要的。socketError 事件并不能认为是异常断线。 首先 socketError 事件并不一定会导致断线,其次若是由客户端机制断开的长连,是不会触发 socketError 事件的。 最简单的方式可以通过 onClose 回调函数触发时系统传入的 code 是否为1000来判断。当然开发者自身也可以通过代码判断是否是自身调用的 close 函数触发的 onclose 事件,监控异常断线。 希望大家在实际应用中能帮助到到大家。
2018-09-29 - (3)强制更新
背景 此前有开发者反馈小程序发布新版本后,新版本覆盖率比较慢,因为小程序的更新机制是异步的,部分用户不会马上应用上新版本。 小程序启动会有两种情况,一种是「冷启动」,一种是「热启动」。 假如用户已经打开过某小程序,然后在一定时间内再次打开该小程序,此时无需重新启动,只需将后台态的小程序切换到前台,这个过程就是热启动;冷启动指的是用户首次打开或小程序被微信主动销毁后再次打开的情况,此时小程序需要重新加载启动。 小程序的异步更新发生在冷启动过程,当发现新版本后,会异步下载新版本的代码包,但不会马上应用上最新版本,需要等小程序下一次冷启动,才会应用上新版本。 解决思路为了解决这个问题,我们内部也经历了数个方案的讨论,这里简单介绍下: 1. 同步检查更新(放弃):可能是最直接的解决思路,但主要问题是会影响小程序的启动速度,当下小程序的更新迭代是非常频繁的,部分用户可能每次启动都命中更新,如果需要同步检查更新+同步下载新的版本,那将会影响这部分用户的启动体验。 2. 模块热替换(放弃):从技术上来说,这是最好的方案,小程序运行起来后,在打开新页面时,马上应用新版本里的页面,但这就会存在新旧逻辑、页面共存问题,对于开发者来说,反而更不好处理,特别是涉及到全局变量时,情况会更复杂,对于我们已有的框架来说,也是一个大挑战,不过这个也是我们之后努力的方向。 3. 定时 check 新版本(目前方案):6.6.3 及以上版本的客户端,会定时 check 最近使用过的小程序是否有发布新版本;如果有,下次打开的时候会同步更新新版本再打开。这可以保证在新版本发布 24 小时后,所有小程序都能使用最新版本。(这部分是微信客户端自身优化,开发者无需关心) 4. 异步更新 + 强制更新(目前方案):同步检查更新与模块热替换两者之间的折衷方案,即还是维持异步更新机制,在异步下载完小程序代码包后,提供重启小程序的能力,这样在遇到紧急问题时可以马上解决。 异步更新 + 强制更新方案介绍从基础库 1.9.90 开始,我们提供了 wx.getUpdateManager 接口,使用该接口,可以获知是否有新版本小程序、新版本是否下载好以及应用新版本的能力。 当小程序冷启动时,会自动向微信后台请求新版本信息,如果有新版本,会马上触发新版本的下载。开发者可以通过 wx.getUpdateManager,获知当前更新的状态。 wx.getUpdateManager 接口会返回一个 UpdateManager 实例,UpdateManager 包含了三个回调: 1. onCheckForUpdate:当小程序向后台请求完新版本信息,会通知这个版本告知检查结果 2. onUpdateReady:当新版本下载完成,会回调这个事件 3. onUpdateFailed: 当新版本下载失败,会回调这个事件 还有重启应用新版本的接口: 1. applyUpdate:当新版本下载完成(onUpdateReady),调用该方法会强制当前小程序应用上新版本并重启 具体示例: [代码]// wx.getUpdateManager 在 1.9.90 才可用,请注意兼容[代码] [代码]const updateManager = wx.getUpdateManager()[代码] [代码]updateManager.onCheckForUpdate(function[代码] [代码](res) {[代码] [代码] // 请求完新版本信息的回调[代码] [代码] console.log(res.hasUpdate)[代码] [代码]})[代码] [代码]updateManager.onUpdateReady(function[代码] [代码]() {[代码] [代码] wx.showModal({[代码] [代码] title: '更新提示',[代码] [代码] content: '新版本已经准备好,是否马上重启小程序?',[代码] [代码] success: function[代码] [代码](res) {[代码] [代码] if[代码] [代码](res.confirm) {[代码] [代码] // 新的版本已经下载好,调用 applyUpdate 应用新版本并重启[代码] [代码] updateManager.applyUpdate()[代码] [代码] }[代码] [代码] }[代码] [代码] })[代码] [代码]})[代码] [代码]updateManager.onUpdateFailed(function[代码] [代码]() {[代码] [代码] // 新的版本下载失败[代码] [代码]})[代码] 更详细信息可以参考 UpdateManager 的详细文档 最佳实践从用户体验上来说,我们还是建议只在非常必要时才强制用户重启更新,例如出现线上紧急 BUG。通常情况下,可以选通过 wx.showModal 弹出选择框让用户选择是否重启更新(实现请参考示例代码)。 如何调试最新版本的微信开发者工具提供了强制更新的调试能力,通过编译模式 - 编辑编译模式 - 勾上「下次编译时模拟更新」即可在开发者工具上调试强制更新功能。 最新开发者工具下载链接 点我。
2022-08-08