最近在使用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("这是类内部的公有方法");
}
}
网友评论