嗨森逛PC管理端
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.
 
 
 
 
high-web/src/app/services/websocket.service.ts

239 lines
7.2 KiB

import {Component, Injectable} from '@angular/core';
import {interval, Subject} from 'rxjs';
import {NzNotificationService} from 'ng-zorro-antd';
@Injectable({
providedIn: 'root'
})
export class WebsocketService {
messageSubject; // subject对象,用于发送事件
private url; // 默认请求的url
private webSocket: WebSocket; // websocket对象
connectSuccess = false; // websocket 连接成功
period = 60 * 1000 * 10; // 10分钟检查一次
serverTimeoutSubscription = null; // 定时检测连接对象
reconnectFlag = false; // 重连
reconnectPeriod = 5 * 1000; // 重连失败,则5秒钟重连一次
reconnectSubscription = null; // 重连订阅对象
runTimeSubscription; // 记录运行连接subscription
runTimePeriod = 60 * 10000; // 记录运行连接时间
constructor(private notification: NzNotificationService) {
this.messageSubject = new Subject();
console.log('开始心跳检测');
// 进入程序就进行心跳检测,避免出现开始就连接中断,后续不重连
this.heartCheckStart();
this.calcRunTime();
}
/**
* 发送消息
* @author Sum1Dream
* @date 2019/1/22
* @param message 发送消息
*/
sendMessage(message) {
this.webSocket.send(message);
}
/**
* 创建新连接
* @author Sum1Dream
* @date 2019/1/22
* @param url 要连接的url
*/
connect(url) {
if (!!url) {
this.url = url;
}
// 创建websocket对象
this.createWebSocket();
}
/**
* 创建连接
* @author Sum1Dream
* @date 2019/1/22
*/
createWebSocket() {
// 如果没有建立过连接,才建立连接并且添加时间监听
this.webSocket = new WebSocket(this.url);
// 建立连接成功
this.webSocket.onopen = (e) => this.onOpen(e);
// 接收到消息
this.webSocket.onmessage = (e) => this.onMessage(e);
// 连接关闭
this.webSocket.onclose = (e) => this.onClose(e);
// 异常
this.webSocket.onerror = (e) => this.onError(e);
}
/**
* 连接打开
* @author Sum1Dream
* @date 2019/1/22
* @param e 打开事件
*/
onOpen(e) {
console.log('websocket 已连接');
// 设置连接成功
this.connectSuccess = true;
// 如果是重连中
if (this.reconnectFlag) {
// 1.停止重连
this.stopReconnect();
// 2.重新开启心跳
this.heartCheckStart();
// 3.重新开始计算运行时间
this.calcRunTime();
}
}
/**
* 接受到消息
* @author Sum1Dream
* @date 2019/1/22
* @param event 接受消息事件
*/
onMessage(event) {
const data = JSON.parse(event.data);
// 将接受到的消息发布出去
// console.log('接收到消息时间', new Date().getTime());
this.notification.success(
data['order']['gasName'] + '加油订单',
'<p>订单号:' + data['order']['orderNo'] + '</p>' +
'<p>加油金额:' + data['order']['totalPrice'] + '</p>' +
'<p>油号:' + data['order']['gasOilNo'] + '</p>' +
'<p>油枪号:' + data['order']['gasGunNo'] + '</p>'
);
const audio = new Audio();
audio.src = data['voice'];
audio.load();
audio.play().then(r => console.log(r));
this.messageSubject.next(true);
}
/**
* 连接关闭
* @author Sum1Dream
* @date 2019/1/22
*/
private onClose(e) {
console.log('连接关闭', e);
this.connectSuccess = false;
this.webSocket.close();
// 关闭时开始重连
this.reconnect();
this.stopRunTime();
// throw new Error('webSocket connection closed:)');
}
/**
* 连接异常
* @author Sum1Dream
* @date 2019/1/22
*/
private onError(e) {
// 出现异常时一定会进onClose,所以只在onClose做一次重连动作
console.log('连接异常', e);
this.connectSuccess = false;
// throw new Error('webSocket connection error:)');
}
/**
* 开始重新连接
* @author Sum1Dream
* @date 2019/1/22
*/
reconnect() {
// 如果已重连,则直接return,避免重复连接
if (this.connectSuccess) {
this.stopReconnect();
console.log('已经连接成功,停止重连');
return;
}
// 如果正在连接中,则直接return,避免产生多个轮训事件
if (this.reconnectFlag) {
console.log('正在重连,直接返回');
return;
}
// 开始重连
this.reconnectFlag = true;
// 如果没能成功连接,则定时重连
this.reconnectSubscription = interval(this.reconnectPeriod).subscribe(async (val) => {
console.log(`重连:${val}`);
const url = this.url;
// 重新连接
this.connect(url);
});
}
/**
* 停止重连
* @author Sum1Dream
* @date 2019/1/22
*/
stopReconnect() {
// 连接标识置为false
this.reconnectFlag = false;
// 取消订阅
if (typeof this.reconnectSubscription !== 'undefined' && this.reconnectSubscription != null) {
this.reconnectSubscription.unsubscribe();
}
}
/**
* 开始心跳检测
* @author Sum1Dream
* @date 2019/1/22
*/
heartCheckStart() {
this.serverTimeoutSubscription = interval(this.period).subscribe((val) => {
// 保持连接状态,重置下
if (this.webSocket != null && this.webSocket.readyState === 1) {
console.log(val, '连接状态,发送消息保持连接');
} else {
// 停止心跳
this.heartCheckStop();
// 开始重连
this.reconnect();
console.log('连接已断开,重新连接');
}
});
}
/**
* 停止心跳检测
* @author Sum1Dream
* @date 2019/1/22
*/
heartCheckStop() {
// 取消订阅停止心跳
if (typeof this.serverTimeoutSubscription !== 'undefined' && this.serverTimeoutSubscription != null) {
this.serverTimeoutSubscription.unsubscribe();
}
}
/**
* 开始计算运行时间
* @author Sum1Dream
* @date 2019/1/25
*/
calcRunTime() {
this.runTimeSubscription = interval(this.runTimePeriod).subscribe(period => {
console.log('运行时间', `${period}分钟`);
});
}
/**
* 停止计算运行时间
* @author Sum1Dream
* @date 2019/1/25
*/
stopRunTime() {
if (typeof this.runTimeSubscription !== 'undefined' && this.runTimeSubscription !== null) {
this.runTimeSubscription.unsubscribe();
}
}
}