magic-chat-im 2.9.2 → 2.9.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/es/common.d.ts +86 -0
- package/es/common.js +92 -0
- package/es/connection-manager.d.ts +83 -0
- package/es/connection-manager.js +434 -0
- package/es/error-handler.d.ts +45 -0
- package/es/error-handler.js +111 -0
- package/es/event-handler.d.ts +14 -0
- package/es/event-handler.js +215 -0
- package/es/heartbeat-manager.d.ts +37 -0
- package/es/heartbeat-manager.js +93 -0
- package/es/im.d.ts +162 -0
- package/es/im.interface.d.ts +234 -0
- package/es/im.interface.js +1 -0
- package/es/im.js +444 -0
- package/es/index.d.ts +7 -0
- package/es/index.js +8 -0
- package/es/logger.d.ts +98 -0
- package/es/logger.js +238 -0
- package/es/message-queue-manager.d.ts +45 -0
- package/es/message-queue-manager.js +128 -0
- package/es/message-sender.d.ts +26 -0
- package/es/message-sender.js +113 -0
- package/es/monitoring-manager.d.ts +48 -0
- package/es/monitoring-manager.js +161 -0
- package/es/reconnect.d.ts +19 -0
- package/es/reconnect.js +279 -0
- package/es/socket.d.ts +29 -0
- package/es/socket.js +163 -0
- package/es/types.d.ts +82 -0
- package/es/types.js +1 -0
- package/es/util.d.ts +11 -0
- package/es/util.js +44 -0
- package/package.json +1 -1
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
import type { RECONNECT_RESON } from './common';
|
|
2
|
+
import type { MessageQueueManager } from './message-queue-manager';
|
|
3
|
+
import type { HeartbeatManager } from './heartbeat-manager';
|
|
4
|
+
import type { MonitoringManager } from './monitoring-manager';
|
|
5
|
+
import type { ConnectionManager } from './connection-manager';
|
|
6
|
+
import type { ReconnectState } from './reconnect';
|
|
7
|
+
import type { MessageBody, MessageData, ReconnectEventData, CloseEventData, ErrorEventData } from './types';
|
|
8
|
+
import type { LoggerConfig } from './logger';
|
|
9
|
+
/**
|
|
10
|
+
* IM 公共参数接口
|
|
11
|
+
*/
|
|
12
|
+
export interface CommonParams {
|
|
13
|
+
/**
|
|
14
|
+
* @description 消息所属应用
|
|
15
|
+
* @default ''
|
|
16
|
+
*/
|
|
17
|
+
appId?: string;
|
|
18
|
+
/**
|
|
19
|
+
* @description 消息所属topic
|
|
20
|
+
* @default ''
|
|
21
|
+
*/
|
|
22
|
+
userId?: string;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* IM 配置选项接口
|
|
26
|
+
*/
|
|
27
|
+
export interface Options {
|
|
28
|
+
/**
|
|
29
|
+
* @description webpush链接地址
|
|
30
|
+
* @default ''
|
|
31
|
+
*/
|
|
32
|
+
url: string;
|
|
33
|
+
/**
|
|
34
|
+
* @description webpush appKey
|
|
35
|
+
* @default ''
|
|
36
|
+
*/
|
|
37
|
+
appKey: string;
|
|
38
|
+
/**
|
|
39
|
+
* @description webpush token
|
|
40
|
+
* @default ''
|
|
41
|
+
*/
|
|
42
|
+
token?: string;
|
|
43
|
+
/**
|
|
44
|
+
* @description getToken
|
|
45
|
+
* @default ''
|
|
46
|
+
*/
|
|
47
|
+
getToken: () => Promise<string>;
|
|
48
|
+
/**
|
|
49
|
+
* @description 默认参数
|
|
50
|
+
* @default {}
|
|
51
|
+
*/
|
|
52
|
+
commonParams?: CommonParams;
|
|
53
|
+
/**
|
|
54
|
+
* @description 最大重连次数
|
|
55
|
+
* @default 10 - 推荐值 (约 3 分钟)
|
|
56
|
+
*
|
|
57
|
+
* 推荐配置:
|
|
58
|
+
* - 5-10 次: 高实时性应用 (~1-3 分钟)
|
|
59
|
+
* - 10-15 次: 标准 IM 应用 (~3-5 分钟) [推荐]
|
|
60
|
+
* - 15-20 次: 保守配置 (~5-8 分钟)
|
|
61
|
+
*
|
|
62
|
+
* 指数退避算法: 1s → 2s → 4s → 8s → 16s → 30s(最大) × N
|
|
63
|
+
* 不推荐超过 20 次,以免长时间无意义的重连尝试
|
|
64
|
+
*/
|
|
65
|
+
reconnectMaxRetry?: number;
|
|
66
|
+
/**
|
|
67
|
+
* @description 连接成功回调
|
|
68
|
+
* @default ''
|
|
69
|
+
*/
|
|
70
|
+
connectCallback?: () => void;
|
|
71
|
+
/**
|
|
72
|
+
* @description 断连回调
|
|
73
|
+
* @default ''
|
|
74
|
+
*/
|
|
75
|
+
disconnectCallback?: () => void;
|
|
76
|
+
/**
|
|
77
|
+
* @description 重连成功回调
|
|
78
|
+
* @default ''
|
|
79
|
+
*/
|
|
80
|
+
reconnectCallback?: (msg: ReconnectEventData) => void;
|
|
81
|
+
/**
|
|
82
|
+
* @description 收到ack回调
|
|
83
|
+
* @default ''
|
|
84
|
+
*/
|
|
85
|
+
ackCallback?: (msg: MessageData) => void;
|
|
86
|
+
/**
|
|
87
|
+
* @description 接收message数据回调
|
|
88
|
+
* @default ''
|
|
89
|
+
*/
|
|
90
|
+
messageCallback?: (msg: MessageBody) => void;
|
|
91
|
+
/**
|
|
92
|
+
* @description webpush异常错误回调
|
|
93
|
+
* @default ''
|
|
94
|
+
*/
|
|
95
|
+
errorCallback?: (err: ErrorEventData) => void;
|
|
96
|
+
/**
|
|
97
|
+
* @description webpush 长链接异常关闭回调,可以弹窗提醒用户刷新页面
|
|
98
|
+
* @default ''
|
|
99
|
+
*/
|
|
100
|
+
closeCallback?: (err: CloseEventData) => void;
|
|
101
|
+
/**
|
|
102
|
+
* @description 支持监听网络状态变化重连, 注意如果开启这个模式,在im 销毁时需要显示调用destroy方法
|
|
103
|
+
* @default false
|
|
104
|
+
*/
|
|
105
|
+
supportNetworkRestoredReconnect?: boolean;
|
|
106
|
+
/**
|
|
107
|
+
* @description 日志配置
|
|
108
|
+
* @default 开发环境: { level: LogLevel.DEBUG, enabled: true }, 生产环境: { level: LogLevel.WARN, enabled: false }
|
|
109
|
+
*
|
|
110
|
+
* @example
|
|
111
|
+
* ```typescript
|
|
112
|
+
* // 使用默认配置(推荐)
|
|
113
|
+
* const im = new IM({ url, appKey, getToken });
|
|
114
|
+
*
|
|
115
|
+
* // 自定义日志配置
|
|
116
|
+
* const im = new IM({
|
|
117
|
+
* url,
|
|
118
|
+
* appKey,
|
|
119
|
+
* getToken,
|
|
120
|
+
* loggerConfig: {
|
|
121
|
+
* level: LogLevel.INFO, // 日志级别
|
|
122
|
+
* enabled: true, // 是否启用
|
|
123
|
+
* timestamp: true, // 显示时间戳
|
|
124
|
+
* prefix: '[我的应用]', // 自定义前缀
|
|
125
|
+
* handler: (level, message, ...args) => {
|
|
126
|
+
* // 自定义处理器(如上报到服务器)
|
|
127
|
+
* if (level === LogLevel.ERROR) {
|
|
128
|
+
* reportToServer({ level, message, args });
|
|
129
|
+
* }
|
|
130
|
+
* },
|
|
131
|
+
* },
|
|
132
|
+
* });
|
|
133
|
+
*
|
|
134
|
+
* // 禁用所有日志
|
|
135
|
+
* const im = new IM({
|
|
136
|
+
* url,
|
|
137
|
+
* appKey,
|
|
138
|
+
* getToken,
|
|
139
|
+
* loggerConfig: { enabled: false },
|
|
140
|
+
* });
|
|
141
|
+
* ```
|
|
142
|
+
*/
|
|
143
|
+
loggerConfig?: Partial<LoggerConfig>;
|
|
144
|
+
/**
|
|
145
|
+
* @description 心跳超时时间(毫秒)
|
|
146
|
+
* @default 60000 (60秒) - 标准环境
|
|
147
|
+
* @default 30000 (30秒) - 移动端环境
|
|
148
|
+
*/
|
|
149
|
+
pingTimeout?: number;
|
|
150
|
+
/**
|
|
151
|
+
* @description 心跳间隔时间(毫秒)
|
|
152
|
+
* @default 10000 (10秒) - 标准环境
|
|
153
|
+
* @default 5000 (5秒) - 移动端环境
|
|
154
|
+
*/
|
|
155
|
+
pingInterval?: number;
|
|
156
|
+
/**
|
|
157
|
+
* @description 页面从隐藏到可见状态的时间阈值(毫秒),超过此时间将触发重连
|
|
158
|
+
* @default 30000 (30秒)
|
|
159
|
+
*/
|
|
160
|
+
hiddenToVisibleTimeThreshold?: number;
|
|
161
|
+
/**
|
|
162
|
+
* @description 连接超时时间(毫秒),建议10-30秒
|
|
163
|
+
* @default 15000 (15秒)
|
|
164
|
+
*/
|
|
165
|
+
connectionTimeout?: number;
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* IM 连接统计信息接口
|
|
169
|
+
*/
|
|
170
|
+
export interface IMConnectionStats {
|
|
171
|
+
totalConnections: number;
|
|
172
|
+
totalReconnections: number;
|
|
173
|
+
totalMessagesSent: number;
|
|
174
|
+
totalMessagesReceived: number;
|
|
175
|
+
totalHeartbeatTimeouts: number;
|
|
176
|
+
firstConnectionTime: number;
|
|
177
|
+
lastConnectTime: number;
|
|
178
|
+
lastDisconnectTime: number;
|
|
179
|
+
totalOnlineTime: number;
|
|
180
|
+
currentOnlineTime: number;
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* IM 实例接口
|
|
184
|
+
* 定义了 IM 类需要实现的所有公共方法和属性
|
|
185
|
+
*/
|
|
186
|
+
export interface IMInstance {
|
|
187
|
+
version: string;
|
|
188
|
+
options: any;
|
|
189
|
+
im: any;
|
|
190
|
+
_reconnect: any;
|
|
191
|
+
_commonParams: any;
|
|
192
|
+
_userClosed: boolean;
|
|
193
|
+
_msgCounter: number;
|
|
194
|
+
_connectionStats: IMConnectionStats;
|
|
195
|
+
_heartbeatManager: HeartbeatManager;
|
|
196
|
+
_messageQueueManager: MessageQueueManager;
|
|
197
|
+
_monitoringManager: MonitoringManager;
|
|
198
|
+
_connectionManager: ConnectionManager;
|
|
199
|
+
emit: (event: string, data?: any) => void;
|
|
200
|
+
on: (event: string, handler: (data?: any) => void) => void;
|
|
201
|
+
_keepAlive: () => void;
|
|
202
|
+
_onPongReceived: () => void;
|
|
203
|
+
_ack: (messageKey: string) => void;
|
|
204
|
+
_send: (data: string) => void;
|
|
205
|
+
_messageKey: () => string;
|
|
206
|
+
_detect: () => boolean;
|
|
207
|
+
connect: () => void;
|
|
208
|
+
reconnect: (code: RECONNECT_RESON, error?: any) => void;
|
|
209
|
+
close: () => void;
|
|
210
|
+
manualReconnect: () => void;
|
|
211
|
+
readyState: () => number;
|
|
212
|
+
sendMessage: (msgBody?: Partial<MessageBody>) => void;
|
|
213
|
+
ping: () => void;
|
|
214
|
+
sendEvent: (data: Record<string, any>) => void;
|
|
215
|
+
errorEvent: (msg: ErrorEventData) => void;
|
|
216
|
+
closeEvent: (msg: CloseEventData) => void;
|
|
217
|
+
reconnectEvent: (msg: ReconnectEventData) => void;
|
|
218
|
+
setUserClosed: (closed: boolean) => void;
|
|
219
|
+
getReconnectState: () => ReconnectState | undefined;
|
|
220
|
+
getReconnectCounter: () => number;
|
|
221
|
+
getReconnectMaxRetry: () => number;
|
|
222
|
+
getQueueSize: () => number;
|
|
223
|
+
getUserClosed: () => boolean;
|
|
224
|
+
getConnectionStats: () => IMConnectionStats;
|
|
225
|
+
getPerformanceMetrics: () => {
|
|
226
|
+
connectionSuccessRate: number;
|
|
227
|
+
messageLossRate: number;
|
|
228
|
+
averageReconnectionTime: number;
|
|
229
|
+
heartbeatTimeoutRate: number;
|
|
230
|
+
};
|
|
231
|
+
resetConnectionStats: () => void;
|
|
232
|
+
destroy: () => void;
|
|
233
|
+
setCommonParams: (param: any) => void;
|
|
234
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/es/im.js
ADDED
|
@@ -0,0 +1,444 @@
|
|
|
1
|
+
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
|
|
2
|
+
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
3
|
+
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
4
|
+
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
|
5
|
+
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } }
|
|
6
|
+
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
|
|
7
|
+
function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
8
|
+
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
|
|
9
|
+
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
10
|
+
/* eslint-disable no-underscore-dangle */
|
|
11
|
+
|
|
12
|
+
/* eslint-disable @typescript-eslint/member-ordering */
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* IM 通讯层
|
|
16
|
+
* 这里需要适配 websocket
|
|
17
|
+
*/
|
|
18
|
+
import mitt from 'mitt';
|
|
19
|
+
import { RECONNECT_RESON, WS_READYSTATE } from "./common";
|
|
20
|
+
import { logger } from "./logger";
|
|
21
|
+
import Reconnect from "./reconnect";
|
|
22
|
+
import { HeartbeatManager } from "./heartbeat-manager";
|
|
23
|
+
import { MessageQueueManager } from "./message-queue-manager";
|
|
24
|
+
import { EventHandler } from "./event-handler";
|
|
25
|
+
import { MessageSender } from "./message-sender";
|
|
26
|
+
import { MonitoringManager } from "./monitoring-manager";
|
|
27
|
+
import { ConnectionManager } from "./connection-manager";
|
|
28
|
+
import { isMobile } from "./util";
|
|
29
|
+
// 定义Ping-Pong超时时间默认值(例如60秒)
|
|
30
|
+
var DEFAULT_PING_TIMEOUT = 60 * 1000;
|
|
31
|
+
// 移动端特殊处理:更短的超时时间
|
|
32
|
+
var DEFAULT_MOBILE_PING_TIMEOUT = 30 * 1000;
|
|
33
|
+
|
|
34
|
+
// 定义定时发送Ping的间隔默认值(例如每10秒一次)
|
|
35
|
+
var DEFAULT_PING_INTERVAL = 10 * 1000;
|
|
36
|
+
// 移动端特殊处理:更频繁的心跳检测
|
|
37
|
+
var DEFAULT_MOBILE_PING_INTERVAL = 5 * 1000;
|
|
38
|
+
|
|
39
|
+
// 页面隐藏到再次可见的时间阈值默认值(例如30秒)
|
|
40
|
+
var DEFAULT_HIDDEN_2_VISIBLE_TIME = 30 * 1000;
|
|
41
|
+
var IM = /*#__PURE__*/function () {
|
|
42
|
+
// 消息计数器
|
|
43
|
+
|
|
44
|
+
function IM(options) {
|
|
45
|
+
var _this = this;
|
|
46
|
+
_classCallCheck(this, IM);
|
|
47
|
+
_defineProperty(this, "version", void 0);
|
|
48
|
+
_defineProperty(this, "options", void 0);
|
|
49
|
+
_defineProperty(this, "emit", void 0);
|
|
50
|
+
_defineProperty(this, "on", void 0);
|
|
51
|
+
_defineProperty(this, "im", void 0);
|
|
52
|
+
// 连接统计信息
|
|
53
|
+
_defineProperty(this, "_connectionStats", void 0);
|
|
54
|
+
// 心跳管理器实例
|
|
55
|
+
_defineProperty(this, "_heartbeatManager", void 0);
|
|
56
|
+
// 消息队列管理器实例
|
|
57
|
+
_defineProperty(this, "_messageQueueManager", void 0);
|
|
58
|
+
// 事件处理器实例
|
|
59
|
+
_defineProperty(this, "_eventHandler", void 0);
|
|
60
|
+
// 消息发送器实例
|
|
61
|
+
_defineProperty(this, "_messageSender", void 0);
|
|
62
|
+
// 监控管理器实例
|
|
63
|
+
_defineProperty(this, "_monitoringManager", void 0);
|
|
64
|
+
// 连接管理器实例
|
|
65
|
+
_defineProperty(this, "_connectionManager", void 0);
|
|
66
|
+
_defineProperty(this, "_hiddenToVisibleTimeThreshold", void 0);
|
|
67
|
+
_defineProperty(this, "_reconnect", void 0);
|
|
68
|
+
_defineProperty(this, "_commonParams", void 0);
|
|
69
|
+
_defineProperty(this, "_userClosed", false);
|
|
70
|
+
// 标记用户是否主动关闭连接
|
|
71
|
+
_defineProperty(this, "_msgCounter", 0);
|
|
72
|
+
var _options$commonParams = options.commonParams,
|
|
73
|
+
commonParams = _options$commonParams === void 0 ? {} : _options$commonParams,
|
|
74
|
+
loggerConfig = options.loggerConfig;
|
|
75
|
+
Object.assign(this, _objectSpread({
|
|
76
|
+
options: options
|
|
77
|
+
}, mitt()));
|
|
78
|
+
|
|
79
|
+
// IM协议版本
|
|
80
|
+
this.version = '1.0';
|
|
81
|
+
|
|
82
|
+
// 标记用户是否主动关闭
|
|
83
|
+
this._userClosed = false;
|
|
84
|
+
|
|
85
|
+
// 初始化连接统计信息
|
|
86
|
+
this._monitoringManager = new MonitoringManager(this);
|
|
87
|
+
this._connectionStats = this._monitoringManager.initializeConnectionStats();
|
|
88
|
+
|
|
89
|
+
// 初始化心跳管理器
|
|
90
|
+
var pingTimeout = options.pingTimeout || (isMobile() ? DEFAULT_MOBILE_PING_TIMEOUT : DEFAULT_PING_TIMEOUT);
|
|
91
|
+
var pingInterval = options.pingInterval || (isMobile() ? DEFAULT_MOBILE_PING_INTERVAL : DEFAULT_PING_INTERVAL);
|
|
92
|
+
this._heartbeatManager = new HeartbeatManager({
|
|
93
|
+
pingTimeout: pingTimeout,
|
|
94
|
+
pingInterval: pingInterval
|
|
95
|
+
}, function () {
|
|
96
|
+
// 心跳超时回调
|
|
97
|
+
logger.error('[IM] Heartbeat timeout, initiating reconnect');
|
|
98
|
+
// 更新心跳超时统计
|
|
99
|
+
_this._monitoringManager.updateHeartbeatTimeoutStats();
|
|
100
|
+
_this.reconnect(RECONNECT_RESON.HEARTBEAT_TIMEOUT);
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
// 初始化消息队列管理器
|
|
104
|
+
this._messageQueueManager = new MessageQueueManager();
|
|
105
|
+
|
|
106
|
+
// 初始化事件处理器
|
|
107
|
+
this._eventHandler = new EventHandler(this);
|
|
108
|
+
|
|
109
|
+
// 初始化消息发送器
|
|
110
|
+
this._messageSender = new MessageSender(this);
|
|
111
|
+
this._hiddenToVisibleTimeThreshold = options.hiddenToVisibleTimeThreshold || DEFAULT_HIDDEN_2_VISIBLE_TIME;
|
|
112
|
+
|
|
113
|
+
// 初始化连接管理器
|
|
114
|
+
this._connectionManager = new ConnectionManager(this, this._hiddenToVisibleTimeThreshold);
|
|
115
|
+
|
|
116
|
+
// 配置日志系统
|
|
117
|
+
if (loggerConfig) {
|
|
118
|
+
logger.setConfig(loggerConfig);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* 重连
|
|
123
|
+
* 1. 心跳超时直接重连,见 _mockHeartbeatTimeout
|
|
124
|
+
* 2. ws失败error重连,见 onError
|
|
125
|
+
* 3. ws非正常关闭,close重连
|
|
126
|
+
* 4. 发消息时,发现ws非连接中状态都重连,见 sendMessage
|
|
127
|
+
* 5. 往外面暴露reconnect重连方法,由外部控制重连
|
|
128
|
+
*/
|
|
129
|
+
this._reconnect = Reconnect(this);
|
|
130
|
+
|
|
131
|
+
// 消息全局参数
|
|
132
|
+
this._commonParams = commonParams;
|
|
133
|
+
|
|
134
|
+
// 添加网络和可见性监听器
|
|
135
|
+
if (this.options.supportNetworkRestoredReconnect) {
|
|
136
|
+
this._connectionManager.attachEventListeners();
|
|
137
|
+
} else if (process.env.NODE_ENV !== 'production') {
|
|
138
|
+
// 开发环境提示:建议启用网络监听以获得更好的用户体验
|
|
139
|
+
logger.warn('[IM] 建议启用 supportNetworkRestoredReconnect 以获得更好的连接稳定性。\n' + '启用后请确保在组件卸载时调用 destroy() 方法。\n' + '示例: new IM({ supportNetworkRestoredReconnect: true, ... })');
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* 销毁 IM 实例
|
|
145
|
+
* 注意:如果开启了 supportNetworkRestoredReconnect,必须显式调用此方法以清理资源
|
|
146
|
+
*/
|
|
147
|
+
_createClass(IM, [{
|
|
148
|
+
key: "destroy",
|
|
149
|
+
value: function destroy() {
|
|
150
|
+
logger.info('[IM] IM SDK instance destroyed');
|
|
151
|
+
|
|
152
|
+
// 移除事件监听器
|
|
153
|
+
this._connectionManager.detachEventListeners();
|
|
154
|
+
|
|
155
|
+
// 解绑WebSocket事件
|
|
156
|
+
if (this.im) {
|
|
157
|
+
this._eventHandler.unbindEvents(this.im);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// 清理定时器
|
|
161
|
+
this._connectionManager.cleanup();
|
|
162
|
+
|
|
163
|
+
// 人为主动关闭连接
|
|
164
|
+
this.close();
|
|
165
|
+
this.setUserClosed(true);
|
|
166
|
+
|
|
167
|
+
// 清理IM实例上的所有事件监听器
|
|
168
|
+
// 由于mitt库没有提供直接清理所有事件监听器的方法,我们记录这个事实
|
|
169
|
+
// 在实际应用中,使用者应该在destroy之前移除所有手动添加的事件监听器
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* 设置全局参数
|
|
173
|
+
* @param {*} param
|
|
174
|
+
*/
|
|
175
|
+
}, {
|
|
176
|
+
key: "setCommonParams",
|
|
177
|
+
value: function setCommonParams(param) {
|
|
178
|
+
this._commonParams = _objectSpread(_objectSpread({}, this._commonParams), param);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* IM建连
|
|
183
|
+
*/
|
|
184
|
+
}, {
|
|
185
|
+
key: "connect",
|
|
186
|
+
value: function connect() {
|
|
187
|
+
this._connectionManager.connect();
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* 重新建立im连接
|
|
192
|
+
*
|
|
193
|
+
* @param code 重连原因
|
|
194
|
+
*/
|
|
195
|
+
}, {
|
|
196
|
+
key: "reconnect",
|
|
197
|
+
value: function reconnect(code, error) {
|
|
198
|
+
this._connectionManager.reconnect(code, error);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* 关闭IM连接,用户主动关闭连接
|
|
203
|
+
*/
|
|
204
|
+
}, {
|
|
205
|
+
key: "close",
|
|
206
|
+
value: function close() {
|
|
207
|
+
this._connectionManager.close();
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* 手动重连(用于达到最大重连次数后)
|
|
212
|
+
*/
|
|
213
|
+
}, {
|
|
214
|
+
key: "manualReconnect",
|
|
215
|
+
value: function manualReconnect() {
|
|
216
|
+
this._connectionManager.manualReconnect();
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* 参考 ws.readyState
|
|
221
|
+
* CONNECTING:值为0,表示正在连接。
|
|
222
|
+
* OPEN:值为1,表示连接成功,可以通信了。
|
|
223
|
+
* CLOSING:值为2,表示连接正在关闭。
|
|
224
|
+
* CLOSED:值为3,表示连接已经关闭,或者打开连接失败。
|
|
225
|
+
*/
|
|
226
|
+
}, {
|
|
227
|
+
key: "readyState",
|
|
228
|
+
value: function readyState() {
|
|
229
|
+
return this._connectionManager.readyState();
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* error回调
|
|
234
|
+
*/
|
|
235
|
+
}, {
|
|
236
|
+
key: "errorEvent",
|
|
237
|
+
value: function errorEvent(msg) {
|
|
238
|
+
this._connectionManager.errorEvent(msg);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* 关闭回调
|
|
243
|
+
*/
|
|
244
|
+
}, {
|
|
245
|
+
key: "closeEvent",
|
|
246
|
+
value: function closeEvent(msg) {
|
|
247
|
+
this._connectionManager.closeEvent(msg);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* 重连回调
|
|
252
|
+
*/
|
|
253
|
+
}, {
|
|
254
|
+
key: "reconnectEvent",
|
|
255
|
+
value: function reconnectEvent(msg) {
|
|
256
|
+
this._connectionManager.reconnectEvent(msg);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* 设置用户关闭状态(用于测试)
|
|
261
|
+
* @param {boolean} closed - 是否为用户关闭
|
|
262
|
+
*
|
|
263
|
+
* @example
|
|
264
|
+
* // 模拟系统错误,允许重连
|
|
265
|
+
* im.setUserClosed(false);
|
|
266
|
+
*
|
|
267
|
+
* // 模拟用户主动关闭,阻止重连
|
|
268
|
+
* im.setUserClosed(true);
|
|
269
|
+
*/
|
|
270
|
+
}, {
|
|
271
|
+
key: "setUserClosed",
|
|
272
|
+
value: function setUserClosed(closed) {
|
|
273
|
+
logger.debug("[IM] Setting _userClosed to ".concat(closed));
|
|
274
|
+
this._userClosed = closed;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
/**
|
|
278
|
+
* 获取用户关闭状态(用于测试和监控)
|
|
279
|
+
* @returns {boolean} 是否为用户主动关闭
|
|
280
|
+
*/
|
|
281
|
+
}, {
|
|
282
|
+
key: "getUserClosed",
|
|
283
|
+
value: function getUserClosed() {
|
|
284
|
+
return this._userClosed;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* 获取重连状态(用于监控)
|
|
289
|
+
* @returns {ReconnectState} 重连状态
|
|
290
|
+
*/
|
|
291
|
+
}, {
|
|
292
|
+
key: "getReconnectState",
|
|
293
|
+
value: function getReconnectState() {
|
|
294
|
+
var _this$_reconnect, _this$_reconnect$getS;
|
|
295
|
+
return (_this$_reconnect = this._reconnect) === null || _this$_reconnect === void 0 || (_this$_reconnect$getS = _this$_reconnect.getState) === null || _this$_reconnect$getS === void 0 ? void 0 : _this$_reconnect$getS.call(_this$_reconnect);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* 获取当前重连次数(用于监控)
|
|
300
|
+
* @returns {number} 当前重连次数
|
|
301
|
+
*/
|
|
302
|
+
}, {
|
|
303
|
+
key: "getReconnectCounter",
|
|
304
|
+
value: function getReconnectCounter() {
|
|
305
|
+
var _this$_reconnect$getC, _this$_reconnect2, _this$_reconnect2$get;
|
|
306
|
+
return (_this$_reconnect$getC = (_this$_reconnect2 = this._reconnect) === null || _this$_reconnect2 === void 0 || (_this$_reconnect2$get = _this$_reconnect2.getCounter) === null || _this$_reconnect2$get === void 0 ? void 0 : _this$_reconnect2$get.call(_this$_reconnect2)) !== null && _this$_reconnect$getC !== void 0 ? _this$_reconnect$getC : 0;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* 获取最大重连次数(用于监控)
|
|
311
|
+
* @returns {number} 最大重连次数
|
|
312
|
+
*/
|
|
313
|
+
}, {
|
|
314
|
+
key: "getReconnectMaxRetry",
|
|
315
|
+
value: function getReconnectMaxRetry() {
|
|
316
|
+
var _this$_reconnect$getM, _this$_reconnect3, _this$_reconnect3$get;
|
|
317
|
+
return (_this$_reconnect$getM = (_this$_reconnect3 = this._reconnect) === null || _this$_reconnect3 === void 0 || (_this$_reconnect3$get = _this$_reconnect3.getMaxRetry) === null || _this$_reconnect3$get === void 0 ? void 0 : _this$_reconnect3$get.call(_this$_reconnect3)) !== null && _this$_reconnect$getM !== void 0 ? _this$_reconnect$getM : 0;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
/**
|
|
321
|
+
* 获取待发送消息队列大小(用于监控)
|
|
322
|
+
* @returns {number} 队列大小
|
|
323
|
+
*/
|
|
324
|
+
}, {
|
|
325
|
+
key: "getQueueSize",
|
|
326
|
+
value: function getQueueSize() {
|
|
327
|
+
// 返回新的消息队列管理器中的待发送任务数量
|
|
328
|
+
return this._messageQueueManager.getSendQueueSize();
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
/**
|
|
332
|
+
* 获取连接统计信息(用于监控)
|
|
333
|
+
* @returns {object} 连接统计信息
|
|
334
|
+
*/
|
|
335
|
+
}, {
|
|
336
|
+
key: "getConnectionStats",
|
|
337
|
+
value: function getConnectionStats() {
|
|
338
|
+
return this._monitoringManager.getConnectionStats();
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
/**
|
|
342
|
+
* 获取性能指标(用于监控)
|
|
343
|
+
* @returns {object} 性能指标
|
|
344
|
+
*/
|
|
345
|
+
}, {
|
|
346
|
+
key: "getPerformanceMetrics",
|
|
347
|
+
value: function getPerformanceMetrics() {
|
|
348
|
+
return this._monitoringManager.getPerformanceMetrics();
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
/**
|
|
352
|
+
* 重置连接统计信息
|
|
353
|
+
*/
|
|
354
|
+
}, {
|
|
355
|
+
key: "resetConnectionStats",
|
|
356
|
+
value: function resetConnectionStats() {
|
|
357
|
+
this._monitoringManager.resetConnectionStats();
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
/**
|
|
361
|
+
* 探测环境是否支持WebSocket
|
|
362
|
+
* 不支持WebSocket就降级long polling
|
|
363
|
+
*/
|
|
364
|
+
}, {
|
|
365
|
+
key: "_detect",
|
|
366
|
+
value: function _detect() {
|
|
367
|
+
return !!(window.WebSocket && window.WebSocket.prototype.send);
|
|
368
|
+
}
|
|
369
|
+
// 端上保持心跳
|
|
370
|
+
}, {
|
|
371
|
+
key: "_keepAlive",
|
|
372
|
+
value: function _keepAlive() {
|
|
373
|
+
var _this2 = this;
|
|
374
|
+
// 使用心跳管理器开始心跳
|
|
375
|
+
this._heartbeatManager.start(function () {
|
|
376
|
+
_this2.ping();
|
|
377
|
+
});
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
/**
|
|
381
|
+
* 收到 Pong 响应
|
|
382
|
+
*/
|
|
383
|
+
}, {
|
|
384
|
+
key: "_onPongReceived",
|
|
385
|
+
value: function _onPongReceived() {
|
|
386
|
+
// 收到 pong,重置心跳超时计时器
|
|
387
|
+
this._heartbeatManager.reset();
|
|
388
|
+
logger.debug('[IM] Pong received, connection is healthy');
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
// 收到后端业务消息的ack
|
|
392
|
+
}, {
|
|
393
|
+
key: "_ack",
|
|
394
|
+
value: function _ack(messageKey) {
|
|
395
|
+
this._messageSender.ack(messageKey);
|
|
396
|
+
}
|
|
397
|
+
}, {
|
|
398
|
+
key: "_messageKey",
|
|
399
|
+
value: function _messageKey() {
|
|
400
|
+
return this._messageSender.messageKey();
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
/**
|
|
404
|
+
* 发送消息
|
|
405
|
+
*/
|
|
406
|
+
}, {
|
|
407
|
+
key: "sendMessage",
|
|
408
|
+
value: function sendMessage() {
|
|
409
|
+
var msgBody = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
410
|
+
this._messageSender.sendMessage(msgBody);
|
|
411
|
+
}
|
|
412
|
+
/**
|
|
413
|
+
* 发送hb消息
|
|
414
|
+
*/
|
|
415
|
+
}, {
|
|
416
|
+
key: "ping",
|
|
417
|
+
value: function ping() {
|
|
418
|
+
this._messageSender.ping();
|
|
419
|
+
}
|
|
420
|
+
/**
|
|
421
|
+
* 发送事件消息
|
|
422
|
+
* @param {Object} data
|
|
423
|
+
*/
|
|
424
|
+
}, {
|
|
425
|
+
key: "sendEvent",
|
|
426
|
+
value: function sendEvent(data) {
|
|
427
|
+
this._messageSender.sendEvent(data);
|
|
428
|
+
}
|
|
429
|
+
/**
|
|
430
|
+
* 发送消息
|
|
431
|
+
* @param {Object} data
|
|
432
|
+
*/
|
|
433
|
+
}, {
|
|
434
|
+
key: "_send",
|
|
435
|
+
value: function _send(data) {
|
|
436
|
+
if (this.im && this.readyState() === WS_READYSTATE.OPEN) {
|
|
437
|
+
var _this$im;
|
|
438
|
+
(_this$im = this.im) === null || _this$im === void 0 || _this$im.send(data);
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
}]);
|
|
442
|
+
return IM;
|
|
443
|
+
}();
|
|
444
|
+
export { IM as default };
|
package/es/index.d.ts
ADDED