首页 > 其他分享 >js实现websocket断线重连功能

js实现websocket断线重连功能

时间:2024-04-02 21:33:45浏览次数:19  
标签:重连 websocket center layui align js var font size

在项目开发中我们可能经常要使用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>

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

标签:重连,websocket,center,layui,align,js,var,font,size
From: https://blog.csdn.net/Qcg0223/article/details/137287120

相关文章

  • Web前端(JS)
    1.JavaScript简介及其导入方式什么是JavaScript?JavaScript简称JS。JavaScript是一种轻量级、解释型、面向对象的脚本语言。它主要被设计用于在网页上实现动态效果,增加用户与网页的交互性。作为一种客户端脚本语言,JavaScript可以直接嵌入HTML,并在浏览器中执行。与HTML和CSS......
  • ETL工具-nifi干货系列 第七讲 处理器JoltTransformJSON(续)
    第六讲教程只简单介绍了Jolt的chain转换模式,本节课介绍下Jolt的各种转换模式。点击的处理器JoltTransformJSON高级配置选项,进行测试Jolt的转换模式。 1、Cardinality:更改了输入JSON数据元素的基数,适用于jsonObj和jsonList之间的转换。list转为obj input{"review......
  • ETL工具-nifi干货系列 第七讲 处理器JoltTransformJSON(续)
    第六讲教程只简单介绍了Jolt的chain转换模式,本节课介绍下Jolt的各种转换模式。点击的处理器JoltTransformJSON高级配置选项,进行测试Jolt的转换模式。1、Cardinality:更改了输入JSON数据元素的基数,适用于jsonObj和jsonList之间的转换。list转为objinput{"review......
  • jsp指令标签
    jsp指令:         种类:1).page指令:对jsp页面的属性进行修改         语法:<%@page        功能:1.静态编码<%@pagecontentType="text/html;charset=gb2312"%>导包<%@pageimport="java.util.Date"%>2)include指令:页面包含3)taglib指令 ......
  • JS- 构造函数调用与常规函数和方法调用的主要区别
    构造函数调用与常规函数和方法调用的主要区别:特征构造函数调用常规函数和方法调用调用方式使用new关键字直接调用函数名或通过对象调用方法参数处理构造函数可以接受任意数量和类型的参数,并且通过this来引用它们函数和方法可以接受任意数量和类型的参数this的值新创建......
  • nodejs在谷歌浏览器中调试
    一.浏览器开启实验室模式在谷歌浏览器中输入网址<chrome://flags/>,进入页面后打开该功能。二.配置js文件我用的是pycharm,首先对需要调试的js文件进行配置,然后填入--inspect-brk三.调试jsDebugger要调试的js文件,然后在谷歌浏览器中新打开一个标签页,打开开发者工具,等待nod......
  • nodeJs 实现视频的转换(超详细教程)
    前段时间拿到一个视频是4k的,没法播放,于是通过node.js  和 ffmpeg实现了视频的转换。在win10系统下实现。所需工具node16.19直接安装ffmpeg-5.1.1-essentials_build解压后重名ffmpeg放到C盘然后配置下环境变量Git-2.42.0.2-64-bit直接安装安装完建一个demo......
  • 使用Apache POI和Jsoup将Word文档转换为HTML
    简介在现代办公环境中,Word文档和HTML页面都是常见的信息表达方式。有时,我们需要将Word文档转换为HTML格式,以便在网页上展示或进行进一步的处理。本文将介绍如何使用ApachePOI库和Jsoup库来实现Word文档到HTML的转换,并处理文档中的图片资源。环境准备Java开发环境Apac......
  • 54.html+css+js网页设计实例/“企业”酒庄主题介绍/web前端期末大作业/
    一、前言  本实例以“企业”酒庄为主题设计,应用html+css+js、图片轮翻效果、留言板、搜索等,供大家参考。【关注作者|获取更多源码(2000+个Web案例源码)|优质文章】;您的支持是我创作的动力!【点赞收藏博文】,Web开发、课程设计、毕业设计有兴趣的联系我交流分享,3Q!二、网页文......
  • P2143 [JSOI2010] 巨额奖金 题解
    P2143[JSOI2010]巨额奖金题解矩阵树定理+Kruskal最小生成树计数。思路MST都是喵喵题。引理1:所有合法的权值相同边的连边方案,得到的连通块情况是相同的。感性理解:如果不相同意味着至少有一条边可以连通一对连通块。所以我们可以这么做:先跑Kruskal标记树边,然后枚举......