济菏高速数据中心代码
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

286 lines
5.6 KiB

/**
* 自定义 WebSocket 扩展对象
*/
class Socket extends WebSocket {
/**
* 要连接的URL;这应该是WebSocket服务器将响应的URL。
*/
url;
/**
* 可选
* 一个协议字符串或者一个包含协议字符串的数组。这些字符串用于指定子协议,这样单个服务器可以实现多个WebSocket子协议
* (例如,您可能希望一台服务器能够根据指定的协议(protocol)处理不同类型的交互)。如果不指定协议字符串,则假定为空字符串。
*/
protocols;
/**
* 令牌(作为身份识别)
*/
tokenSN;
/**
* 密码(验证是否合法)
*/
password;
/**
* 心跳周期(单位:秒)
*/
heartRate;
/**
* 心跳状态
* 0:没有心跳
* 1:存在心跳
*/
lifeState;
/**
* 有心跳的
* @type {number}
*/
ALIVE = 1;
/**
* 无心跳的
* @type {number}
*/
DIE = 0;
constructor(options) {
super(options.url, options.protocols);
this.url = options.url;
this.protocols = options.protocols;
const tokenSN = options.tokenSN;
if (!tokenSN || typeof tokenSN !== 'string') {
throw new TypeError('参数 tokenSN 错误!tokenSN 必须是一个有效字符串');
}
this.tokenSN = tokenSN;
const password = options.password;
if (!password) {
throw new TypeError('参数 password 错误!参数 password 不存在');
}
this.password = password;
const heartRate = options.heartRate;
if (isNaN(heartRate)) {
throw new TypeError('参数 heartRate 错误!参数 heartRate 必须是数字');
}
this.heartRate = heartRate;
}
/**
* 心跳
*/
heartbeat() {
if (this.lifeState === this.ALIVE) {
return;
}
const engine = setInterval(() => {
// 如果连接处于连接状态则发送心跳
if (this.readyState === this.OPEN) {
try {
this.send(JSON.stringify({
method : 'heartbeat'
}));
this.lifeState = this.ALIVE;
}catch (e) {}
}
// 连接关闭状态时,关闭心跳
if (this.readyState === this.CLOSED) {
clearInterval(engine);
this.lifeState = this.DIE;
}
}, this.heartRate * 1000 * 0.8);
}
/**
* 登录认证
*/
login() {
if (this.readyState !== this.OPEN) {
return;
}
let loginInfo = {
method : 'login',
params : {
tokenSN : this.tokenSN,
password : this.password
}
};
this.send(JSON.stringify(loginInfo));
}
/**
* 初始化
* @param options
*/
static initialize(options) {
Socket.instance = new Socket(options);
// 连接打开时事件
Socket.instance.addEventListener('open', (event) => {
const onopen = Socket.onopen;
if (typeof onopen === 'function') {
onopen(event);
}
// 登录认证
Socket.instance.login();
// 心跳保活
Socket.instance.heartbeat();
});
Socket.instance.addEventListener('close', (event) => {
const onclose = Socket.onclose;
if (typeof onclose === 'function') {
onclose(event);
}
// 10 秒尝试重连
setTimeout(() => {
console.warn('websocket 已断开连接,尝试再次连接');
Socket.initialize(options);
}, 10 * 1000)
});
Socket.instance.addEventListener('error', (event) => {
const onerror = Socket.onerror;
if (typeof onerror === 'function') {
onerror(event);
}
});
Socket.instance.addEventListener('message', (event) => {
const onmessage = Socket.onmessage;
const data = event.data;
if (typeof onmessage === 'function') {
onmessage(data);
}
const msg = JSON.parse(data) || {};
let params = msg.params || {};
let subEvent = params.subEvent;
if (subEvent === 'sub') {
let content = params.content;
content = JSON.parse(content);
const requestId = content.requestId;
if (requestId) {
const socket = Socket.instance;
const subEvent = socket.subEvent[requestId];
if (subEvent) {
const callback = subEvent.callback;
if (typeof callback === 'function') {
callback(content);
}
}
}
}
});
}
/**
* 订阅事件
* @type {{}}
*/
subEvent = {}
static send(data) {
let subCallback = {
callback: undefined,
then(callback) {
if (typeof callback === 'function') {
this.callback = callback;
}
}
}
const socket = Socket.instance
if (socket === null) return subCallback;
socket.send(JSON.stringify(data));
const params = data.params || {};
const subEvent = params.subEvent || '';
const content = params.content || {};
const id = content.id;
if (id) {
if (subEvent === 'sub') {
socket.subEvent[id] = subCallback;
}else if (subEvent === 'unsub') {
delete socket.subEvent[id];
}
}
return subCallback;
}
}
/**
* socket 实例对象
* @type {null}
*/
Socket.instance = null;
/**
* 用于指定连接关闭后的回调函数。
* @type {null}
*/
Socket.onclose = null;
/**
* 用于指定连接失败后的回调函数。
* @type {null}
*/
Socket.onerror = null;
/**
* 用于指定当从服务器接受到信息时的回调函数。
* @type {null}
*/
Socket.onmessage = null;
/**
* 用于指定当从服务器接受到信息时的回调函数。
* @type {null}
*/
Socket.onopen = null;
export { Socket };