js实现websocket断线重连功能

在项目开发中我们可能经常要使用websocket技术,当连接发生断线后,如果不进行页面刷新将不能正常接收来自服务端的推送消息。为了有效避免这种问题,我们需要在客户端做断线重连处理。当网络或服务出现问题后,客户端会不断检测网络状态,如果服务恢复,客户端则会自动重新连接,并断开本地检测网络的定时器。

一、未做断线检测情况

  • 1、项目效果

通过控制台可看到一旦连接关闭,将无法再次收到来自服务器的推送消息。

在这里插入图片描述

  • 2、未整改前代码

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>排队叫号系统</title>
    <link rel="stylesheet" href="/app/admin/component/pear/css/pear.css" />
    <link rel="stylesheet" href="/app/admin/admin/css/reset.css" />
</head>
<style>
    html{
        font-size:14px
    }
    .pear-container{
        background-color: #0d48ff;
    //background-color: #2e6fff

    }

    *{
        color:white;

    }
    .layui-row{
        width: 100%;
    }
    body{
        position: absolute;
    }
    .call-footer {
        left: 0;
        bottom: 0;
        position: fixed;
        text-align: center;
        padding: 10px;
        font-size: 16px;
    }
    .call-header{
        display: flex;
        justify-content: space-between;
        line-height: 40px;
        text-align: center;
        border-bottom: 2px dashed #85b8b6;
    }
    .isemer{
        color: red;
    }
    .call-header>div{
        font-size: 30px;
        font-family: "楷体","YaHei Consolas Hybrid", Consolas, "微软雅黑", "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Helvetica, "Monaco", courier, monospace;
        font-weight: 800;
    }
    #hd-logo>img{
        width: 200px;
    }
    #hd-title {
        font-size: 24px;
    }
    #hd-desc{
        font-size: 14px;
    }
    /*设置显示当前呼叫患者信息*/
    #call-place{
        height: 28px;
        text-align: center;
        line-height: 28px;
        font-size: 18px;
    //color: #6fc9cc;
        border-bottom: 2px dashed #85b8b6;
    }
    .dis-dept{
        display: flex;
        justify-content:flex-start;
        font-size: 28px;
        align-items: center;
    }
    .disp-title{
        display: flex;
        justify-content: center;
        align-items: center;
        text-align: center;
        padding-right:30px;
        border-right: 3px dashed #21f3ff;
        margin-top: 20px;
        min-width: 200px;
        height: 75vh;
    }
    .disp-title-content{
        flex:1;
        display: flex;
        justify-content: center;
        align-items: center;
        text-align: center;
        font-size: 120px;
        border: 10px solid #f8fff7;
        border-radius: 50%;
        line-height: 100%;
        width: 180px;
        height: 180px;
    }
    .disp-content{
        flex:1;
        display: flex;
        justify-content: center;
        align-items: center;
        height: 75vh;
        padding-left: 20px;
    }
    /*字体大小设置*/
    .dispc-text{
        font-size: 60px;

        overflow: hidden;


    }
    .layui-layer{
        z-index: 9999; /*保证在最上层*/
        background-color: rgba(0,0,0,0.5); /*背景半透明*/
    }

    @keyframes twinkle {
        0% {
            opacity: 0.9;

        }
        100% {
            opacity: 0.2;

        }
    }



</style>
<body class="pear-container">

<div class="layui-fluid" >
    <div class="row call-header">
        <div id="hd-logo"><img src="/app/admin/upload/files/20231128/656599ce1fd4.png" alt=""></div>
        <div id="hd-title">1号窗口</div>
        <div id="hd-desc">2023-11-28 15:00:00</div>
    </div>
    <div style="display: none" class="row" id="call-place">
        请C003号 王小宝到1号窗口采血
    </div>
    <div class="layui-row"  id="call-display">
        <div class="dis-dept">
            <div class="disp-title">
                <div class="disp-title-content"><?php echo $config['num'];?></div>
            </div>
            <div class="disp-content" id="disp-con-htm">
                <!--<marquee direction="up">-->
                <div class="dispc-text">尚未呼叫 <br></div>
                <!--</marquee>-->
            </div>
        </div>
    </div>

</div>
<div class="layui-row call-footer" >
    请保持安静,耐心等待呼叫!
</div>

<script src="/app/admin/component/layui/layui.js"></script>
<script src="/app/admin/component/pear/pear.js"></script>
<script src="/app/admin/admin/js/common.js"></script>
<script src="/app/queue/component/tools.js"></script>
<script src="/app/queue/component/rpm2h5.js"></script>
<script>
    //=========定义显示时间功能结束===================
    function clock() {
        var time = new Date().toLocaleString();
        var htm = '<i class="fa fa-clock-o"></i>' + time;
        document.getElementById('hd-desc').innerHTML=htm;
    };
    setInterval("clock()", 1000);
</script>
<script>

    var socket = "";
    var token = "room"+readQueryVariable('id','1');
    console.log(token);
    // var isUpdate = readQueryVariable('isUpdate','0');
    //  var ws_url = "ws://192.168.40.100:7272?token="+token;
    var ws_url = "ws://192.168.40.100:7272?token="+token;
    var callMark = "就诊";

    layui.use(["table", "form", "common", "popup", "util","layer"], function() {
        let table = layui.table;
        let form = layui.form;
        let $ = layui.$;
        let common = layui.common;
        let util = layui.util;
        let layer = layui.layer;
        var loopTimes = 0 ;
        // 创建一个新的WebSocket对象
        var socket = new WebSocket(ws_url);
        // 连接打开时执行的函数
        socket.onopen = function(event) {
            console.log("已成功连接到服务器");
            // 发送一个消息给服务器
            //socket.send("你好,服务器!");
        };
        // 接收到服务器消息时执行的函数
        socket.onmessage = function(event) {
            loopTimes++;
            console.log("从服务器接收到的消息: " + event.data);

        };
        // 当连接关闭时执行的函数
        socket.onclose = function(event)
        {
            console.log("连接已关闭");
        };

        // 当出现错误时执行的函数
        socket.onerror = function(error) {
            console.log("发生错误: " + error);
        };

    })

</script>
</body>

二、做了断线检测情况

  • 1、重连效果

通过控制台观察可发现,在客户端连接成功后,可接收到服务端推送过来的消息,当服务端关闭后,会触发自动重连定时器,当定时器检测到服务连接成功后,会自动完成连接,并可正常接收来自服务端推送的消息。

在这里插入图片描述

  • 2、支持断线重连完整代码

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>排队叫号系统</title>
    <link rel="stylesheet" href="/app/admin/component/pear/css/pear.css" />
    <link rel="stylesheet" href="/app/admin/admin/css/reset.css" />
</head>
<style>
    html{
        font-size:14px
    }
    .pear-container{
        background-color: #0d48ff;
    //background-color: #2e6fff

    }

    *{
        color:white;

    }
    .layui-row{
        width: 100%;
    }
    body{
        position: absolute;
    }
    .call-footer {
        left: 0;
        bottom: 0;
        position: fixed;
        text-align: center;
        padding: 10px;
        font-size: 16px;
    }
    .call-header{
        display: flex;
        justify-content: space-between;
        line-height: 40px;
        text-align: center;
        border-bottom: 2px dashed #85b8b6;
    }
    .isemer{
        color: red;
    }
    .call-header>div{
        font-size: 30px;
        font-family: "楷体","YaHei Consolas Hybrid", Consolas, "微软雅黑", "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Helvetica, "Monaco", courier, monospace;
        font-weight: 800;
    }
    #hd-logo>img{
        width: 200px;
    }
    #hd-title {
        font-size: 24px;
    }
    #hd-desc{
        font-size: 14px;
    }
    /*设置显示当前呼叫患者信息*/
    #call-place{
        height: 28px;
        text-align: center;
        line-height: 28px;
        font-size: 18px;
    //color: #6fc9cc;
        border-bottom: 2px dashed #85b8b6;
    }
    .dis-dept{
        display: flex;
        justify-content:flex-start;
        font-size: 28px;
        align-items: center;
    }
    .disp-title{
        display: flex;
        justify-content: center;
        align-items: center;
        text-align: center;
        padding-right:30px;
        border-right: 3px dashed #21f3ff;
        margin-top: 20px;
        min-width: 200px;
        height: 75vh;
    }
    .disp-title-content{
        flex:1;
        display: flex;
        justify-content: center;
        align-items: center;
        text-align: center;
        font-size: 120px;
        border: 10px solid #f8fff7;
        border-radius: 50%;
        line-height: 100%;
        width: 180px;
        height: 180px;
    }
    .disp-content{
        flex:1;
        display: flex;
        justify-content: center;
        align-items: center;
        height: 75vh;
        padding-left: 20px;
    }
    /*字体大小设置*/
    .dispc-text{
        font-size: 60px;

        overflow: hidden;


    }
    .layui-layer{
        z-index: 9999; /*保证在最上层*/
        background-color: rgba(0,0,0,0.5); /*背景半透明*/
    }

    @keyframes twinkle {
        0% {
            opacity: 0.9;

        }
        100% {
            opacity: 0.2;

        }
    }



</style>
<body class="pear-container">

<div class="layui-fluid" >
    <div class="row call-header">
        <div id="hd-logo"><img src="/app/admin/upload/files/20231128/656599ce1fd4.png" alt=""></div>
        <div id="hd-title">1号窗口</div>
        <div id="hd-desc">2023-11-28 15:00:00</div>
    </div>
    <div style="display: none" class="row" id="call-place">
        请C003号 王小宝到1号窗口采血
    </div>
    <div class="layui-row"  id="call-display">
        <div class="dis-dept">
            <div class="disp-title">
                <div class="disp-title-content"><?php echo $config['num'];?></div>
            </div>
            <div class="disp-content" id="disp-con-htm">
                <!--<marquee direction="up">-->
                <div class="dispc-text">尚未呼叫 <br></div>
                <!--</marquee>-->
            </div>
        </div>
    </div>

</div>
<div class="layui-row call-footer" >
    请保持安静,耐心等待呼叫!
</div>

<script src="/app/admin/component/layui/layui.js"></script>
<script src="/app/admin/component/pear/pear.js"></script>
<script src="/app/admin/admin/js/common.js"></script>
<script src="/app/queue/component/tools.js"></script>
<script src="/app/queue/component/rpm2h5.js"></script>
<script>
    //=========定义显示时间功能结束===================
    function clock() {
        var time = new Date().toLocaleString();
        var htm = '<i class="fa fa-clock-o"></i>' + time;
        document.getElementById('hd-desc').innerHTML=htm;
    };
    setInterval("clock()", 1000);
</script>
<script>

    var socket = "";
    var token = "room"+readQueryVariable('id','1');
    console.log(token);
    // var isUpdate = readQueryVariable('isUpdate','0');
    //  var ws_url = "ws://192.168.40.100:7272?token="+token;
    var ws_url = "ws://192.168.40.100:7272?token="+token;
    var callMark = "就诊";

    layui.use(["table", "form", "common", "popup", "util","layer"], function() {
        let table = layui.table;
        let form = layui.form;
        let $ = layui.$;
        let common = layui.common;
        let util = layui.util;
        let layer = layui.layer;
        var loopTimes = 0 ;
        function connectWS(){
            try{
                socket = new WebSocket(ws_url);
                // 连接打开时执行的函数
                socket.onopen = function(event) {
                    console.log("已成功连接到服务器");
                    // 发送一个消息给服务器
                    socket.send(token);
                };

                // 接收到服务器消息时执行的函数
                socket.onmessage = function(event) {
                    console.log("从服务器接收到的消息: " + event.data);
                };

                // 当连接关闭时执行的函数
                socket.onclose = function(event)
                {
                    console.log("连接已关闭");
                    reConnect();
                };

                // 当出现错误时执行的函数
                socket.onerror = function(error) {
                    console.log("发生错误: " + error);
                };

            }catch(ex){
                console.log(ex.message);

            }


        };
        // 调用链接socket函数
        connectWS();


        // 断线重新连接websocket
        function reConnect()
        {
            let timeId =  setInterval(function(){
                console.log("正在努力重连。。。");
                if(socket.readyState===WebSocket.CLOSED)
                {
                    connectWS();
                    // 重新连接成功后清除定时器
                    clearInterval(timeId);
                }
            },3000);

        }
    })
</script>
</body>

希望各位小伙伴们都能学会了!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

ubuntu-server部署hive-part3-安装mysql

参照 https://blog.csdn.net/qq_41946216/article/details/134345137 操作系统版本&#xff1a;ubuntu-server-22.04.3 虚拟机&#xff1a;virtualbox7.0 部署mysql 下载上传 下载地址 https://downloads.mysql.com/archives/community/ 以root用户上传&#xff0c;/usr/loc…

Transformer模型-softmax的简明介绍

今天介绍transformer模型的softmax softmax的定义和目的&#xff1a; softmax&#xff1a;常用于神经网络的输出层&#xff0c;以将原始的输出值转化为概率分布&#xff0c;从而使得每个类别的概率值在0到1之间&#xff0c;并且所有类别的概率之和为1。这使得Softmax函数特别适…

利用IP地址判断羊毛用户:IP数据云提供IP风险画像

在当今数字化社会&#xff0c;互联网已经成为人们日常生活和商业活动中不可或缺的一部分。然而&#xff0c;随着网络的普及&#xff0c;网络欺诈行为也日益猖獗&#xff0c;其中包括了羊毛党这一群体。羊毛党指的是利用各种手段获取利益、奖励或者优惠而频繁刷取优惠券、注册账…

微信小程序自定义弹窗组件

业务背景&#xff1a;弹窗有时字体较多&#xff0c;超过7个字&#xff0c;不适用wx.showToast. 组件代码 <view class"toast-box {{isShow? show:}}" animation"{{animationData}}"><view class"toast-content" ><view class&q…

【FTP,EMail】

文章目录 FTPFTP&#xff1a;文件传输协议FTP: 控制连接与数据连接分开FTP命令、响应 EMail电子邮件&#xff08;EMail&#xff09;邮件服务器EMail: SMTP [RFC 2821]SMTP&#xff1a;总结 FTP FTP&#xff1a;文件传输协议 向远程主机上传输文件或从远程主机接收文件。客户/服…

抖音视频关键词批量下载工具|视频爬虫采集软件

抖音视频批量提取工具&#xff0c;搜索即下载&#xff0c;轻松获取所需视频&#xff01; 正文&#xff1a; 想要轻松获取抖音上的精彩视频吗&#xff1f;现在&#xff0c;有了我们的抖音视频批量提取工具&#xff0c;一切变得简单易行&#xff01;Q:290615413无论是针对特定关…

美摄科技AI智能图像矫正解决方案

图像已经成为了企业传播信息、展示产品的重要媒介&#xff0c;在日常拍摄过程中&#xff0c;由于摄影技巧的限制和拍摄环境的复杂多变&#xff0c;许多企业面临着图像内容倾斜、构图效果不佳等挑战&#xff0c;这无疑给企业的形象展示和信息传递带来了不小的困扰。 美摄科技深…

55、美国德克萨斯大学奥斯汀分校、钱德拉家族电气与计算机工程系:通过迁移学习解决BCI个体差异性[不得不说,看技术还得是老美]

2024年2月5日跨被试最新文章&#xff1a; 德州州立大学奥斯汀分校研究团队最近的一项研究成果&#xff0c;通过非侵入式的脑机接口&#xff0c;可以让被试不需要任何校准就可以使用脑机接口设备&#xff0c;这意味着脑机接口具备了大规模被使用的潜力。 一般来说&#xff0c;…

杰理芯片AC79——物联网远程点亮/关闭LED灯

杰理芯片的封装简直太香了&#xff08;比STM32香多了&#xff09;&#xff0c;SDK也封装得很好&#xff0c;对于我这种手残党简直不要太友好。赶紧学起来&#xff0c;快速实现你想要的功能吧&#xff01; 芯片选型 杰理AC79 资料文档 环境搭建以及点亮第一盏灯请访问&#x…

大话设计模式之抽象工厂模式

抽象工厂模式&#xff08;Abstract Factory Pattern&#xff09;是一种创建型设计模式&#xff0c;它提供了一种方式来创建一系列相关或依赖对象的家族&#xff0c;而无需指定其具体类。该模式通过提供一个抽象工厂接口&#xff0c;定义了一组可以创建不同类型对象的方法&#…

【JavaEE】_Spring MVC项目上传文件

目录 1. 文件上传具体实现 2. 保存文件 1. 文件上传具体实现 .java文件内容如下&#xff1a; package com.example.demo.controller;import com.example.demo.Person; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.Multip…

2013年认证杯SPSSPRO杯数学建模A题(第二阶段)护岸框架全过程文档及程序

2013年认证杯SPSSPRO杯数学建模 A题 护岸框架 原题再现&#xff1a; 在江河中&#xff0c;堤岸、江心洲的迎水区域被水流长期冲刷侵蚀。在河道整治工程中&#xff0c;需要在受侵蚀严重的部位设置一些人工设施&#xff0c;以减弱水流的冲刷&#xff0c;促进该处泥沙的淤积&…

SpringData ElasticSearch - 简化开发,完美适配 Spring 生态

目录 一、SpringData ElasticSearch 1.1、环境配置 1.2、创建实体类 1.3、ElasticsearchRestTemplate 的使用 1.3.1、创建索引 设置映射 1.3.2、简单的增删改查 1.3.3、搜索 1.4、ElasticsearchRepository 1.4.1、使用方式 1.4.2、简单的增删改查 1.4.3、分页排序查…

【路径规划论文整理(1)】Path Deformation Roadmaps(附带对PRM改进算法、同伦映射的整理)

本系列主要是对精读的一些关于路径搜索论文的整理&#xff0c;包括了论文所拓展的其他一些算法的改进思路。 这是本系列的第一篇文章&#xff1a; Jaillet, Lonard & Simon, Thierry. (2008). Path Deformation Roadmaps: Compact Graphs with Useful Cycles for Motion Pl…

Windows下编译TinyXML(XML文件解析)

作者&#xff1a;翟天保Steven 版权声明&#xff1a;著作权归作者所有&#xff0c;商业转载请联系作者获得授权&#xff0c;非商业转载请注明出处 TinyXML是什么&#xff1f; TinyXML是一个轻量级的C XML解析器&#xff0c;它提供了一种简单的方法来解析和操作XML文档。TinyXM…

【XR806开发板试用】简单点灯-- 基于SPI控制W2812矩阵幻彩动图和字幕显示系统

1.效果展示 1.gif 动图展示 2.字幕展示 2.软件开发流程 2.1 全志XR806 基本开发流程 使用指南 自己踩过的坑 必须app开头 鸿蒙hb 依赖python 环境。建议使用conda虚拟环境 下载开启硬件校验和烧录重启 2.2 W2812 简单介绍 不是科普文&#xff0c;自行百度 /*WS2812B T…

Mac下Docker Desktop starting的解决方法

记录下自己在新增了一个新的容器后&#xff0c;Disk Size过大导致启动Docker Desktop会一直卡在Docker Desktop starting&#xff0c;并且重启无效的解决方法。该方法无需重新卸载&#xff0c;并且能保留原有的镜像和容器。 一、确认问题 首先确认Docker.raw大小以确认是否和笔…

vivado 高级编程功能1

适用于 7 系列、 UltraScale 和 UltraScale FPGA 和 MPSoC 的回读和验证 为 7 系列器件生成已加密文件和已经过身份验证的文件 注释 &#xff1a; 如需获取其它信息 &#xff0c; 请参阅《使用加密确保 7 系列 FPGA 比特流的安全》 ( XAPP1239 ) 。 要生成加密比特流…

【蓝桥杯嵌入式】13届程序题刷题记录及反思

一、题目分析 考察内容&#xff1a; led按键&#xff08;短按&#xff09;PWM输出&#xff08;PA1&#xff09;串口接收lcd显示 根据PWM输出占空比调节&#xff0c;高频与低频切换 串口接收&#xff08;指令解析&#xff09;【中断接收】 2个显示界面 led灯闪烁定时器 二…

Python读取Excel根据每行信息生成一个PDF——并自定义添加文本,可用于制作准考证

文章目录 有点小bug的:最终代码(无换行):有换行最终代码无bug根据Excel自动生成PDF,目录结构如上 有点小bug的: # coding=utf-8 import pandas as pd from reportlab.pdfgen import canvas from reportlab.lib.pagesizes import letter from reportlab.pdfbase import pdf…