|
|
@@ -1,3 +1,4 @@
|
|
|
+import { v4 } from 'uuid'
|
|
|
import { Package40, Package50 } from './package';
|
|
|
import moment from 'moment'
|
|
|
|
|
|
@@ -77,6 +78,8 @@ export class MTP2WebSocket<T extends Package40 | Package50> {
|
|
|
/** 重连状态发生改变时的回调 */
|
|
|
onReconnectChangeState?: (obj: MTP2WebSocket<T>, state: ReconnectChangeState) => void;
|
|
|
|
|
|
+ /** 实例唯一标识 */
|
|
|
+ private uuid = '';
|
|
|
/** 报文类型,0 - 4.0行情报文,1 - 5.0交易报文 */
|
|
|
private packageType;
|
|
|
/** WebSocket 对象 */
|
|
|
@@ -104,8 +107,6 @@ export class MTP2WebSocket<T extends Package40 | Package50> {
|
|
|
private beatInterval = 10 * 1000;
|
|
|
/** 心跳回复超时时间,默认为15秒 */
|
|
|
private beatTimeoutInterval = 15 * 1000;
|
|
|
- /** 外部是否要求停止断网重连操作标志 */
|
|
|
- private isBrokenReconnecting = false;
|
|
|
|
|
|
private readyState?: Promise<MTP2WebSocket<T>>;
|
|
|
|
|
|
@@ -128,11 +129,13 @@ export class MTP2WebSocket<T extends Package40 | Package50> {
|
|
|
this.stopBeatTimer();
|
|
|
this.host = host || this.host;
|
|
|
this.connState = 'Connecting';
|
|
|
- this.isBrokenReconnecting = false;
|
|
|
console.log(this.packageType, this.host, '正在连接');
|
|
|
|
|
|
this.readyState = new Promise((resolve, reject) => {
|
|
|
+ const uuid = v4();
|
|
|
+ this.uuid = uuid;
|
|
|
this.socket = new WebSocket(this.host);
|
|
|
+
|
|
|
// 连接成功
|
|
|
this.socket.onopen = () => {
|
|
|
console.log(this.packageType, this.host, '连接成功');
|
|
|
@@ -141,16 +144,13 @@ export class MTP2WebSocket<T extends Package40 | Package50> {
|
|
|
this.onConnected && this.onConnected(this);
|
|
|
resolve(this);
|
|
|
}
|
|
|
- // 连接断开
|
|
|
+ // 连接断开(CLOSING有可能延迟)
|
|
|
this.socket.onclose = () => {
|
|
|
- console.warn(this.packageType, this.host, '连接已断开');
|
|
|
- this.socket = undefined;
|
|
|
- this.readyState = undefined;
|
|
|
- this.connState = 'Unconnected';
|
|
|
- this.onClosed && this.onClosed(this);
|
|
|
-
|
|
|
- // 如果重连过程中主动断开了就不再进行重连
|
|
|
- if (!this.isBrokenReconnecting) {
|
|
|
+ // 判断是否当前实例
|
|
|
+ // 如果连接断开后不等待 onclose 响应,由于 onclose 延迟的原因可能会在创建新的 ws 实例后触发,导致刚创建的实例被断开进入重连机制
|
|
|
+ if (this.uuid === uuid) {
|
|
|
+ console.warn(this.packageType, this.host, '连接已断开');
|
|
|
+ this.reset();
|
|
|
this.reconnect();
|
|
|
}
|
|
|
}
|
|
|
@@ -177,11 +177,23 @@ export class MTP2WebSocket<T extends Package40 | Package50> {
|
|
|
* 主动断开连接,断开后不会自动重连
|
|
|
*/
|
|
|
close() {
|
|
|
+ console.warn(this.packageType, this.host, '主动断开');
|
|
|
clearTimeout(this.reconnectTimer);
|
|
|
this.stopBeatTimer();
|
|
|
- this.isBrokenReconnecting = true;
|
|
|
+ this.uuid = v4();
|
|
|
this.reconnectCount = 0;
|
|
|
this.socket?.close();
|
|
|
+ this.reset(); // 不等待 ws.onclose 响应强制重置实例
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 重置实例
|
|
|
+ */
|
|
|
+ private reset() {
|
|
|
+ this.socket = undefined;
|
|
|
+ this.readyState = undefined;
|
|
|
+ this.connState = 'Unconnected';
|
|
|
+ this.onClosed && this.onClosed(this);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -450,26 +462,26 @@ export class MTP2WebSocket<T extends Package40 | Package50> {
|
|
|
*/
|
|
|
private reconnect() {
|
|
|
this.stopBeatTimer();
|
|
|
- if (this.isBrokenReconnecting || this.connState === 'Connecting') return;
|
|
|
-
|
|
|
- this.reconnectCount++;
|
|
|
- console.log(this.packageType, this.host, `5秒后将进行第${this.reconnectCount}次重连`);
|
|
|
-
|
|
|
- this.reconnectTimer = window.setTimeout(() => {
|
|
|
- this.readyState = undefined;
|
|
|
- this.onReconnectChangeState && this.onReconnectChangeState(this, ReconnectChangeState.BeginReconnect);
|
|
|
-
|
|
|
- this.conn().then(() => {
|
|
|
- // 重连成功
|
|
|
- this.reconnectCount = 0;
|
|
|
- this.onReconnectChangeState && this.onReconnectChangeState(this, ReconnectChangeState.ReconnectSuccessed);
|
|
|
- }).catch(() => {
|
|
|
- if (!this.isBrokenReconnecting) {
|
|
|
- console.warn(this.packageType, this.host, `第${this.reconnectCount}次重连失败`);
|
|
|
- this.onReconnectChangeState && this.onReconnectChangeState(this, ReconnectChangeState.FailAndWaitPeriod);
|
|
|
- }
|
|
|
- })
|
|
|
- }, this.reconnectInterval);
|
|
|
+ if (this.connState !== 'Connecting') {
|
|
|
+ this.reconnectCount++;
|
|
|
+ console.log(this.packageType, this.host, `5秒后将进行第${this.reconnectCount}次重连`);
|
|
|
+
|
|
|
+ this.reconnectTimer = window.setTimeout(() => {
|
|
|
+ this.readyState = undefined;
|
|
|
+ this.onReconnectChangeState && this.onReconnectChangeState(this, ReconnectChangeState.BeginReconnect);
|
|
|
+
|
|
|
+ this.conn().then(() => {
|
|
|
+ // 重连成功
|
|
|
+ this.reconnectCount = 0;
|
|
|
+ this.onReconnectChangeState && this.onReconnectChangeState(this, ReconnectChangeState.ReconnectSuccessed);
|
|
|
+ }).catch(() => {
|
|
|
+ if (this.reconnectCount) {
|
|
|
+ console.warn(this.packageType, this.host, `第${this.reconnectCount}次重连失败`);
|
|
|
+ this.onReconnectChangeState && this.onReconnectChangeState(this, ReconnectChangeState.FailAndWaitPeriod);
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }, this.reconnectInterval);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
/**
|