websocket onclose方法什么时候触发_WebSocket断开重连解决方案,心跳重连实践

bb2335ffad73526b08d685e7caf0aab9.png

    WebSocket是前后端交互的长连接,服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对话,属于服务器推送技术的一种。项目中,我们经常会使用WebSocket和服务器建立持久的连接。

    但是前后端也会因为某些不明因素链接断开(我就是因为经常断网38ef39795caee3ffd92a43f946bab5e2.png),导致前后端都没有反馈的情况

    e5793ad49711612151f588fb257ff8c6.png

所以为了保持链接的稳定性和持续性,心跳重连就必须整上去了035a34c479add2bef160e6c5fec99d16.png035a34c479add2bef160e6c5fec99d16.png035a34c479add2bef160e6c5fec99d16.png,也顺便记录一下实现心跳重连的流程

    在使用WebSocket的时候,如果网络突然断开,WebSocketd是不会触发任何事件的,所以前端程序无法得知当前链接是否断开。但是这个时候使用WebSocket.send方法的时候,浏览器会发现消息发不出去,隔一段时间之后(貌似每个浏览器隔的时间不相同),会触发onclose函数。利用这点9775052bbe25aa2aaae875bd3995e3b6.png,我们可以在send不出消息并触发onclose之后,进行重连

    当然后端也可能出现异常,他收到了这个消息,但是没响应回来,前端也收不到通知,差不多就是你给一个人打电话,那niao人不说话的情况,问题你还不知道他在不在。所以这种情况我们要隔段时间send一次,假如超过一定时间没收到回应,那就默认是异常了,就触发重连。

WebSocket的各个绑定事件:

let ws = new WebSocket(url);ws.onopen = function () {   //something}ws.onmessage = function (event) {   //something}ws.onclose = function () {    //something}ws.onerror = function () {    //something}

好了,按照这个思路,开始:

// 心跳检测let heartCheck = {    timeout: 60000, // 超时时间    timer: null,    serverTimer: null,    reset: function(){        clearTimeout(this.timer);     this.start();    },    start: function(){        this.timer = setTimeout(function(){            ws.send('connectTest');        }, this.timeout)    }}

定义了一个心跳检测,当open的时候,执行heartCheck.start()方法,然后onmessage收到信息之后调用heartCheck.reset()方法重置,这样每次onmessage就触发send,达到循环发送的效果。

当send失败的时候,隔一段时间会自动触发onclose,所以要在onclose的时候调用重连

ws.onclose = function () {    console.log('onclose');    reconnect();}

重连的时候需要注意防止重复连接,还要设置延迟,避免请求太频繁

let lockReconnect  = false;/** * @method reconnect ws重新连接 * @description lockReconnect防止重复连接,时间戳避免在失败时候会频繁建立ws连接 */ function reconnect() {    if(lockReconnect) return;    lockReconnect = true;    //没连接上会一直重连,设置延迟避免请求过多    setTimeout(function () {        createWebSocket(); // 创建webSocket连接的方法        lockReconnect = false;    }, 2000);}

如此上面流程就解决了如断网send不出消息的时候重连的效果,测试的时候可以手动断网测,亲测有效a6e31c759ee3c2eb67e05bedc3038df0.png

好了,现在假设后端异常,没数据返回,onmessage就进不去,得另外想办法。所以在每次send的时候的setTimeout内再加一个setTimeout,就是,如果里面这个setTimeout执行了,那就不等了,我觉得他是挂了,重连。

// 心跳检测let heartCheck = {    timeout: 60000, // 超时时间    timer: null,    serverTimer: null,    reset: function(){        clearTimeout(this.timer);        clearTimeout(this.serverTimer);     this.start();    },    start: function(){        let ts = this;        this.timer = setTimeout(function(){            ws.send('connectTest');            // 超出时间内未响应就主动关闭链接,关闭链接会触发重连            ts.serverTimer = setTimeout(function(){                ws.onclose();            }, ts.timeout)                    }, this.timeout)    }}

如果onmessage收到消息,执行了reset会清空所有的timer,重新计时, nice~~~。

这样就完成了websocket的心跳重连,归纳一下代码:

let lockReconnect = false; //避免重复连接let ws;// 心跳检测let heartCheck = {    timeout: 60000,    timer: null,    serverTimer: null,    reset: function(){        clearTimeout(this.timer);        clearTimeout(this.serverTimer);     this.start();    },    start: function(){        let ts = this;        this.timer = setTimeout(function(){            ws.send('connectTest');            ts.serverTimer = setTimeout(function(){                ws.onclose();            }, ts.timeout)        }, this.timeout)    }}// 创建WebSocket链接function createWebSocket () {    if ("WebSocket" in window) {        if (!url) return        ws = new WebSocket(url);                // WebSocket事件方法        initEventHandle();    } else {        console.log('您的浏览器不支持websocket')    }}/** * @method initEventHandle 初始化ws各个事件的方法 */function initEventHandle (url) {    ws.onopen = function () {        heartCheck.start();        console.log('链接成功:', url);    }    //获得消息事件    ws.onmessage = function(data, state) {        // 收到消息的时候重置倒计时        heartCheck.reset();                //something            }    ws.onerror = function() {        message('error', 'WebSocket连接错误!正在重连');        reconnect();    }    ws.onclose = function () {        console.log('onclose');        reconnect();    }}/** * @method reconnect ws重新连接 * @description lockReconnect防止重复连接,时间戳避免在失败时候会频繁建立ws连接 */function reconnect() {    if(lockReconnect) return;    lockReconnect = true;    //没连接上会一直重连,设置延迟避免请求过多    setTimeout(function () {        createWebSocket();        lockReconnect = false;    }, 2000);}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/261701.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

matlab计算离散卷积

一.卷积的数学运算 (1)定义法 (2)图解法 (3)竖式乘法 二.matlab中计算离散卷积使用conv()函数 conv(a,b) 计算序列a与b的卷积 以上图中的习题为例 matlab代码如下: n1[ -2 -1 0 1 2 3 4 5]; …

Maven中使用本地JAR包

为什么80%的码农都做不了架构师&#xff1f;>>> 在Maven项目中使用本地JAR包有两种方法&#xff1a; 1、使用system scope <dependencies><dependency><groupId>org.richard</groupId><artifactId>my-jar</artifactId><ver…

折半查找法(二分查找法)

一.举例 二.算法时间复杂度 假设一共有n个元素 第一次折半元素个数变为n/2; 第二次折半元素个数变为n/4; 第三次折半元素个数变为n/8&#xff1b; 。。。。。 第k次折半元素个数变为n/2^k; 。。。。。 假设k次找到&#xff0c;即为n/2^k1&#xff1b; klog2(n); 三.函数实现 …

悬浮截图软件_Windows最好用截图工具,QQ第一,它第二

大家平时可能都有自己惯用截图工具&#xff0c;比如 Snipaste、PickPick、QQ 截图&#xff0c;还有 Windows 自带的 WinShiftS 截图快捷键等等。如果你不是工具控&#xff0c;那一般来说 QQ 截图和 Windows 快截键就是最简单方便的两个截图工具了。但是真要说简单方便&#xff…

[摘记]数值方法04——函数求值

注&#xff1a;以下来自《C数值算法一书》&#xff0c;仅对章节内容做摘要&#xff0c;为的是给自己扫盲&#xff0c;不涉及算法。 这里只讨论一些最清晰明了的一般方法。 1. 级数与其收敛性 思想&#xff1a;解析函数可在某点x0的邻域内展开成级数&#xff1a;。用这个级数可以…

java文件处理之压缩,分割

http://blog.csdn.net/ycg01/article/details/1366648 java文件处理之压缩,分割 标签&#xff1a; javaexceptionimportnullbytefile2006-11-05 00:30 1574人阅读 评论(1) 收藏 举报分类&#xff1a;点滴&#xff08;12&#xff09; 版权声明&#xff1a;本文为博主原创文章&am…

Hook KiUserExceptionDispatcher参数指针错误的问题

跟了一个晚上,终于解决了 大概要实现的是用这个函数替换ntdll中的KiUserExceptionDispatcher,实现方法如下: VOID NTAPI KiUserExceptionDispatcher(PEXCEPTION_RECORD pExcptRec,PCONTEXT pContext) { DWORD retValue; if (RtlDispatchException(pExcptRec,pContext)) { retVa…

Docker image Introduce

Docker 的image是运行的基本.例如我们build一个image时, 在Dockerfile每条指令会产生一个可读写的image, 下一条指令使用上一条指令产生的image为基础, 继续产生image(然后删除上一个image), 如果指令没有对image有修改的动作, 那么可以使用image cache. 所有的指令执行完, 生成…

vue 筛选组件_记一个复杂组件(Filter)的从设计到开发

此文前端框架使用 rax&#xff0c;全篇代码暂未开源&#xff08;待开源&#xff09;原文链接地址&#xff1a;Nealyang/PersonalBlog前言貌似在面试中&#xff0c;你如果设计一个 react/vue 组件&#xff0c;貌似已经是司空见惯的问题了。本文不是理论片&#xff0c;更多的是自…

python的正则表达式 re

2019独角兽企业重金招聘Python工程师标准>>> 原文发表在&#xff1a; http://luy.li/2010/05/12/python-re/ 延伸阅读&#xff1a;python的 内建函数 和 subprocess 。此文是本系列的第三篇文章了&#xff0c;和之前一样&#xff0c;内容出自官方文档&#xff0c;但…

福克斯保养明细

福克斯轮胎厚度&#xff1a; 胎冠厚度在13mm左右(胎冠花纹深7mm、胎冠厚6mm&#xff09;&#xff0c; 胎侧厚度5mm。 现在的轿车轮胎一般胎面胶层厚度都比较厚&#xff0c;以165/70R13 锦湖KR19轮胎为例:花纹深度为7毫米&#xff0c;缓冲层1&#xff0d;1.5毫米&#xff0c;冠带…

USACO 1.1 Your Ride Is Here

今天开始切USACO 加油 /* ID: aznfy1 PROG: ride LANG: C */ #include <iostream> #include <fstream> #include <string> #include <stdio.h>using namespace std;char a[10],b[10];int main() {freopen("ride.in","r",stdin);f…

Mysql支持的数据类型(总结)

2019独角兽企业重金招聘Python工程师标准>>> 一.数值类型 Mysql支持所有标准SQL中的数值类型&#xff0c;其中包括严格数据类型(INTEGER,SMALLINT,DECIMAL,NUMBERIC)&#xff0c;以及近似数值数据类型(FLOAT,REAL,DOUBLE PRESISION),并在此基础上进行扩展。 扩展后增…

uniapp 获取到js文件var一个变量怎么获取到这个变量值_浅析Js中const,let,var的区别及作用域...

理解&#xff1a;let变量的作用域只能在当前函数中js中const,let,var的区别及作用域_lianzhang861的博客-CSDN博客​blog.csdn.net全局作用域中&#xff0c;用 const 和 let 声明的变量不在 window 上&#xff0c;那到底在哪里&#xff1f;如何去获取&#xff1f;​blog.csdn.n…

C语言求十个数中最大值

一.代码 #define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> int main() {int arr[] { 1,2,3,4,5,63,7,8,9,11 };int sz sizeof(arr) / sizeof(arr[0]);int max arr[0];int i 0;for (i 1; i < 10; i){if (arr[i] > max)max arr[i];}printf("%d\n&qu…

ubuntu20.04安装timeshift最新方法

总结&#xff1a; 现在可以使用如下代码安装 sudo apt-get update sudo apt-get install timeshift原因&#xff1a; 在尝试Timeshift系统备份与还原中的方法时&#xff0c; sudo apt-add-repository -y ppa:teejee2008/ppa运行失败。 更改为以下代码&#xff1a; sudo a…

SQL Server安全(6/11):执行上下文与代码签名(Execution Context and Code Signing)

在保密你的服务器和数据&#xff0c;防备当前复杂的攻击&#xff0c;SQL Server有你需要的一切。但在你能有效使用这些安全功能前&#xff0c;你需要理解你面对的威胁和一些基本的安全概念。这篇文章提供了基础&#xff0c;因此你可以对SQL Server里的安全功能充分利用&#xf…

索引超出数组界限是什么意思_从V8源码分析一个JS 数组的内存占用问题

前段时间&#xff0c;在排查一个问题的时候&#xff0c;遇到了一个有点令人困惑的情况&#xff0c;有下面这两段代码&#xff1a;const a new Array(99999); a[99998] undefined;const b new Array(99999); b[99999] undefined;我们通过 node --inspect-brk 来分别运行这两…

C语言打印九九乘法口诀

一.代码 #define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> int main() {int i 0;int j 0;for (i 1; i < 10; i){for (j 1; j < i; j){printf("%d*%d%-2d", i, j, i * j);}printf("\n");}return 0; }二.运行结果

自动机理论、形式语言和计算导论提纲

我真的是觉得这门课太虚了。。这个总结基于名教材《自动机理论、语言和计算导论》&#xff08;机械工业&#xff09;&#xff0c;也可以说是这本书的总结。由于这门课里很多罗马字母&#xff0c;打字很困难所以能省略的公式都不写了&#xff0c;可以算是入门介绍了。这里省略的…