详解微信小程序实现WebSocket心跳重连


Posted in Javascript onJuly 31, 2018

最近在开发小程序用到了WebSocket,小程序提供了相应的原生API,与H5的API使用方式上有一些区别,所以流行的H5的一些成熟的类库使用起来有些困难,而原生API又存在一些缺陷,所以就自己实现了一套心跳重连机制。

惯例,先简单介绍一下Websocket。

Websocket简介

Websocket是什么

WebSocket 是一种网络通信协议。RFC6455 定义了它的通信标准。

WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。

为什么需要Websocket

HTTP 协议是一种无状态的、无连接的、单向的应用层协议。它采用了请求/响应模型。通信请求只能由客户端发起,服务端对请求做出应答处理。

所以当我们想服务器主动给客户端发送消息,HTTP是做不到的,我们只能使用轮询或者长轮询来实现类似的功能,这样的方式效率低并且浪费资源,为了解决这样的问题,WebSocket诞生了。

小程序中的WebSocket

小程序WebSocket的API

把你给懒得!自己官网看去!

为什么要做心跳重连

在使用原生WebSocket的时候,我们经常会感觉不太稳定,服务端发送的消息有时候客户端接收不到,或者是客户端发送的消息服务端接收不到,虽然WebSocket也提供了onError和onClose的方法,但是经常会有各种未知情况导致断开连接而并不触发Error或Close事件。这样就导致实际连接已经断开了,而客户端和服务端却不知道,还在傻傻的等着消息来。

所以我们要解决的问题就很清晰了:

保证连接状态,连接断开时让客户端与服务端都能知道,进而重连。

上代码

页面载入后,我们连接socket先

onLoad(){
  this.linkSocket()
 },
 linkSocket(){
  let that = this
  wx.connectSocket({
   url: app.globalData.wsUrl + 'websocket?' + this.data.taskId + '&' + this.data.userId,
   success() {
    console.log('连接成功')
    that.initEventHandle()
   }
  })
 },

绑定事件

然后调用initEventHandle来绑定各种各样的事件

initEventHandle(){
  let that = this
  wx.onSocketMessage((res) => {
   //收到消息
  })
  wx.onSocketOpen(()=>{
   console.log('WebSocket连接打开')
  })
  wx.onSocketError(function (res) {
   console.log('WebSocket连接打开失败')
  })
  wx.onSocketClose(function (res) {
   console.log('WebSocket 已关闭!')
  })
 },

这个先放在这我们一会往里填东西

断线重连

reconnect(){
  if (this.lockReconnect) return;
  this.lockReconnect = true;
  clearTimeout(this.timer)
  if (this.data.limit<12){
   this.timer = setTimeout(() => {
    this.linkSocket();
    this.lockReconnect = false;
   }, 5000);
   this.setData({
    limit: this.data.limit+1
   })
  }
 },

我们设置一个锁和最大的重连次数,避免出现无限重连的情况,为了不给服务器太大的压力我这里设置的是5秒重试一次,最多请求12次。

改造一下initEventHandle这样我们就可以实现一般的触发Error的断线重连。

initEventHandle(){
  let that = this
  wx.onSocketMessage((res) => {
   //收到消息
  })
  wx.onSocketOpen(()=>{
   console.log('WebSocket连接打开')
  })
  wx.onSocketError((res)=>{ 
   console.log('WebSocket连接打开失败')
   this.reconnect()
  })
  wx.onSocketClose((res)=> {
   console.log('WebSocket 已关闭!')
   this.reconnect()
  })
 },

关键的来的---心跳对象

先撸为敬

let heartCheck = {
 timeout: 10000, 
 timeoutObj: null,
 serverTimeoutObj: null,
 reset: function () {
  clearTimeout(this.timeoutObj);
  clearTimeout(this.serverTimeoutObj);
  return this;
 },
 start: function () {
  this.timeoutObj = setTimeout(()=> {
   console.log("发送ping");
   wx.sendSocketMessage({
    data:"ping",
    // success(){
    //  console.log("发送ping成功");
    // }
   });
   this.serverTimeoutObj = setTimeout(() =>{
    wx.closeSocket(); 
   }, this.timeout);
  }, this.timeout);
 }
};

心跳对象内timeout为每10秒发一次心跳,timeoutObj、serverTimeoutObj是清除定时器用的对象,reset方法重置定时器,start发送心跳。

继续改造我们的initEventHandle

initEventHandle(){
  let that = this
  wx.onSocketMessage((res) => {
   //收到消息
   if (res.data == "pong"){
    heartCheck.reset().start()
   }else{
    \\处理数据
   }
  })
  wx.onSocketOpen(()=>{
   console.log('WebSocket连接打开')
   heartCheck.reset().start()
  })
  wx.onSocketError((res)=>{ 
   console.log('WebSocket连接打开失败')
   this.reconnect()
  })
  wx.onSocketClose((res)=> {
   console.log('WebSocket 已关闭!')
   this.reconnect()
  })
 },

打开连接的时候调用start开始心跳,每隔10秒向服务端发送消息"ping",服务端接收到消息后给我们回个话"pong",就好像微信聊天。

在吗?

在吗?

在吗?

别看在吗很烦,至少能确定你们俩还是好友,要不他把你拉黑了你还不知道(有点跑题了)

如果超过10秒服务端还没回复“pong”,则认为连接断开的

我擦,敢删我好友,我这东北爷们的暴脾气这能忍?我把你也删了 。。。。。。。。。。。然后赶紧重新申请好友

这是暴脾气的客户端直接把连接关闭,调用closeSocket,可是一关闭我们的onSocketClose事件又去重连了(渣男)

至此,心跳重连实现完毕

总结

Socket心跳重连在H5中可以有类似的实现,也有成熟的第三方库,比如说stomp+websocket+sockjs可以实现更加完整的更兼容的socket连接方案,可以下次给大家分享(看我心情)。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
javascript 限制输入和粘贴(IE,firefox测试通过)
Nov 14 Javascript
javascript打开新窗口同时关闭旧窗口
Jan 16 Javascript
javascript window.open打开新窗口后无法再次打开该窗口问题的解决方法
Apr 12 Javascript
用javascript读取xml文件读取节点数据
Aug 12 Javascript
js实现创建删除html元素小结
Sep 30 Javascript
微信小程序 animation API详解及实例代码
Oct 08 Javascript
js 图片转base64的方式(两种)
Apr 24 Javascript
vue cli3.0结合echarts3.0与地图的使用方法示例
Mar 26 Javascript
JQuery获取可视区尺寸和文档尺寸及制作悬浮菜单示例
May 14 jQuery
JS快速实现简单计算器
Apr 08 Javascript
TypeScript的安装、使用、自动编译的实现
Apr 10 Javascript
javascript使用正则表达式实现注册登入校验
Sep 23 Javascript
前端axios下载excel文件(二进制)的处理方法
Jul 31 #Javascript
JS构造一个html文本内容成文件流形式发送到后台
Jul 31 #Javascript
vue导出html、word和pdf的实现代码
Jul 31 #Javascript
JavaScript函数节流和函数去抖知识点学习
Jul 31 #Javascript
JS使用遮罩实现点击某区域以外时弹窗的弹出与关闭功能示例
Jul 31 #Javascript
微信网页授权并获取用户信息的方法
Jul 30 #Javascript
axios简单实现小程序延时loading指示
Jul 30 #Javascript
You might like
php利用cookie实现访问次数统计代码
2011/05/19 PHP
两级联动select刷新后其值保持不变的实现方法
2014/01/27 PHP
ThinkPHP模板中判断volist循环的最后一条记录的验证方法
2014/07/01 PHP
Windows下Apache + PHP SESSION丢失的解决过程全纪录
2015/04/07 PHP
PHP简单创建压缩图的方法
2016/08/24 PHP
php实现构建排除当前元素的乘积数组方法
2018/10/06 PHP
Laravel框架实现抢红包功能示例
2019/10/31 PHP
用JavaScript和注册表脚本实现右键收藏Web页选中文本
2007/01/28 Javascript
用js做一个小游戏平台 (一)
2009/12/29 Javascript
原生js写的放大镜效果
2012/08/22 Javascript
js简单实现用户注册信息的校验代码
2013/11/15 Javascript
Nodejs中调用系统命令、Shell脚本和Python脚本的方法和实例
2015/01/01 NodeJs
Web前端框架bootstrap实战【第一次接触使用】
2016/12/28 Javascript
vue-quill-editor实现图片上传功能
2017/08/08 Javascript
浅谈Angular HttpClient简单入门
2018/05/04 Javascript
react-native滑动吸顶效果的实现过程
2019/06/03 Javascript
JavaScript 自定义html元素鼠标右键菜单功能
2019/12/02 Javascript
vscode 插件开发 + vue的操作方法
2020/06/05 Javascript
js实现购物车商品数量加减
2020/09/21 Javascript
Vue中引入svg图标的两种方式
2021/01/14 Vue.js
[14:25]教你分分钟做大人:主宰(HEROS)
2014/12/08 DOTA
[28:07]完美世界DOTA2联赛PWL S3 Phoenix vs INK ICE 第二场 12.13
2020/12/17 DOTA
[06:59]DOTA2-DPC中国联赛3月7日Recap集锦
2021/03/11 DOTA
python抽象基类用法实例分析
2015/06/04 Python
python3中利用filter函数输出小于某个数的所有回文数实例
2019/11/24 Python
如何基于Python制作有道翻译小工具
2019/12/16 Python
python实现3D地图可视化
2020/03/25 Python
Python extract及contains方法代码实例
2020/09/11 Python
Python Web项目Cherrypy使用方法镜像
2020/11/05 Python
如何将无状态会话Bean发布为WEB服务,只有无状态会话Bean可以发布为WEB服务?
2015/12/03 面试题
党员的自我评价范文
2014/01/02 职场文书
北京申奥口号
2014/06/19 职场文书
企业贷款委托书格式
2014/09/12 职场文书
群众路线党员个人整改措施
2014/10/27 职场文书
贷款承诺书
2015/01/20 职场文书
慈善募捐倡议书
2015/04/27 职场文书