IT@程序员猿媛简友广场

如何写一个完整的JavaScript类,将现有代码整合

2019-12-09  本文已影响0人  程就人生

最近在使用HTML5的WebSocket,在写WebSocket测试用例的时候,很多方法都分散在页面的JavaScript里面,很想把这些零碎的方法整合成一个类,然后以js文件的形式引入,引入后以类的形式调用,这样页面看起来岂不是干净了很多。

说做就做,拿起以前做的demo,就在这上面进行修改吧。SpringBoot整合Netty与websocket客户端进行对话 通过这篇笔记,把里面的js整理一下,整理以后对比一下修改前后的结果。

在把HTML5页面里的WebSocket代码整理成一个类的同时,也遇到了一些问题:
1.在JavaScript里面,如何声明一个类;
2.类里面的公有属性和私有属性如何区分;
3.类里面的一个方法即需要在外面调用,有需要在内部调用,这该如何写;
一直都在零零碎碎地写一些JS方法,要整合成一个功能相对完整的类来,还是需要翻下资料的。

下面就直接上代码,websocket.js的内容如下:

/**
 * websocket的构造方法
 * @param wconfig 连接websocket的基础参数
 */
var WebSocketHtml5 = function(wconfig){
    //ws客户端,私有变量
    var socket;
    //参数传递
    var wconfig = wconfig;
    //把本身引用赋值到一变量上
    var _self = this;
    //避免重复连接
    var lockReconnect = false;
    //重连标识
    var reconnectFlag;
    //重连时间,4S
    var reconnectTime = 4000;
    //心跳检测时间50s
    var heartTime = 50000;
    //websocket默认是传输字符串的,需要改为arraybuffer二进制传输类型
    var binaryType = wconfig.binaryType!=undefined&&wconfig.binaryType!=''?wconfig.binaryType:"";
    //连接参数
    var wsUrl = "ws://localhost:"+wconfig.imServerPort+"/websocket/"+wconfig.userUid;
    //接收到的二位数组,第一个是消息类型,第二个是消息体
    var resData;
    //创建连接,公有方法
    this.createWebSocket=function(){
        try {
            if(typeof(WebSocket) == "undefined") {  
                console.log("您的浏览器不支持WebSocket");  
            }else{
                console.log("您的浏览器支持WebSocket");  
            }
            socket = new WebSocket(wsUrl);
            //websocket默认是传输字符串的,需要改为arraybuffer二进制传输类型         
            //socket.binaryType = binaryType;
            //初始化
            init();
        } catch(e) {
            console.log('catch');
            reconnect();
        }
    }   
    //初始化
    function init() {
        socket.onclose = function () {
            console.log('链接关闭');
            reconnect();
        };
        socket.onerror = function() {
            console.log('发生异常了');
            reconnect();
        };
        socket.onopen = function () {
            //心跳检测重置
            heartCheck.start(socket, wconfig);
        };
        socket.onmessage = function (event) {
            //接收数据
            var resData = JSON.parse(event.data);
            //心跳保持
            heartCheck.start(socket, wconfig);
            //接收数据的返回
            receive(resData);
        }
    }
    /**
     * 消息的发送
     * msgData 消息结构体,包括以下几个属性
     * @param toUser 消息接收人
     * @param textContent 消息内容
     * @param contentType 消息类型
     */
    this.send = function (msgData){     
        //发送数据
        socket.send(JSON.stringify(msgData));
    }   
    //重新连接
    function reconnect() {
      if(lockReconnect) {
        return;
      };
      lockReconnect = true;
      //没连接上会一直重连,设置延迟避免请求过多
      reconnectFlag && clearTimeout(reconnectFlag);
      reconnectFlag = setTimeout(function () {
          _self.createWebSocket();
        lockReconnect = false;
      }, reconnectTime);//重连时间
    }   
    //生成消息的uuid
    function uuid() {
        var s = [];
        var hexDigits = "0123456789abcdef";
        for (var i = 0; i < 36; i++) {
            s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
        }
        s[14] = "4";  // bits 12-15 of the time_hi_and_version field to 0010
        s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1);  // bits 6-7 of the clock_seq_hi_and_reserved to 01
        s[8] = s[13] = s[18] = s[23] = "";
     
        var uuid = s.join("");
        return uuid;
    }
}
//心跳检测
var heartCheck =  {
    timeout: 50000,//心跳检测时间
    timeoutObj: null,
    serverTimeoutObj: null,
    start: function(socket, wconfig){
        var self = this;
        this.timeoutObj && clearTimeout(this.timeoutObj);
        this.serverTimeoutObj && clearTimeout(this.serverTimeoutObj);
        this.timeoutObj = setTimeout(function(){
            //这里发送一个心跳,后端收到后,返回一个心跳消息,
            //onmessage拿到返回的心跳就说明连接正常
            console.log(' socket心跳检测');
            //发送心跳 start
            var object={}
            object.content = "心跳检测";
            object.toUser = wconfig.userUid;
            object.fromUser= wconfig.userUid;
            socket.send(JSON.stringify(object));
            //发送心跳 end
            self.serverTimeoutObj = setTimeout(function() {
                socket.close();
            }, self.timeout);
        }, this.timeout)
    }
};

下面再看页面里的使用:

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" >
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
</head>
<body>
<p>发送信息:<input type="text" id="txt" ></input></p>
<p>接收人:<input type="text" id="toUser" ></input></p>
<p><button id="button" >发送消息</button></p>
<p id="recvContent">

</p>
<script src="http://www.jq22.com/jquery/jquery-1.10.2.js"></script>
<script th:src="@{/websocket.js}"></script>
<script th:inline="javascript" >
    //websocket连接相关参数
    var imData={};
    imData.userUid=[[${userUid}]];
    imData.imServerPort=[[${imServerPort}]];
    //以类的形式进行调用
    var websocketHtml5 = new WebSocketHtml5(imData);
    //创建websocket
    websocketHtml5.createWebSocket();
    //获取接收到的数据
    var receive = function(resData){
        if(resData!=undefined) {
            $("#recvContent").append('<div style="width:300px;text-align:left;"><span >'+resData.fromUser + '发送:' + resData.content + '</span></div><br/>');
        } 
    };
    //发送信息回车键
    $("#txt").keydown(function(event){ 
        if(event.keyCode==13){ 
            $("#button").click();
        } 
    });    
    //按钮点击事件
    $("#button").click(function(){
        var object={}
        object.content = $("#txt").val();
        object.toUser = $("#toUser").val();
        object.fromUser= imData.userUid;
        $("#txt").val("");
        $("#recvContent").append('<div style="width:300px;text-align:right;"><span >发送给'+object.toUser + ':' + object.content + '</span></div><br/>');
        websocketHtml5.send(object);
    });    
</script>

</body>
</html>

最后,验证结果,和修改之前的测试结果保持一致,这说明已经成功地将方法整合成了一个类;


在JavaScript里面编写类,大致有三种方法,一种是构造函数方式,一种是原型方式,还有一种就是构造函数+原型,这里使用的是构造函数+原型的混合方式。下面就这三种类型一一说明一下。

一、构造函数式
顾名思义,像写函数一样写类;

function test(a,b){
   // 用var定义,代表类的私有属性
    var a=a;
  // 用this关键字定义,代表类的公有属性,可通过实例访问
    this.b=b;
 //这个很重要,对于公有方法,可以使用该变量进行访问
   var _self=this;
  // 私有方法,只能在类的内部访问
  funciton c(){
     console.log("这是类内部的私有方法");
  }
  //公有方法,可以通过类的实例进行访问
  this.d=function(){
     console.log("这是类内部的公有方法");
  }
}

二、原型方式
原型方式其实就是上面示例中的心跳检测,这种写法看起来比较优雅、舒服;

var test={
a:'',//public属性
b:'',//公有属性
//公有方法
c:function(a,b){
this.a=a;
this.b=b;
console.log("这是类内部的公有方法");
}
}

参考资料:
https://www.cnblogs.com/xdp-gacl/p/3700840.html

上一篇下一篇

猜你喜欢

热点阅读