mm_expand 2.0.1 → 2.0.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/lib/base.js +221 -71
- package/lib/event.js +568 -159
- package/lib/eventer.js +20 -16
- package/lib/file.js +9 -9
- package/lib/lang.js +2 -5
- package/lib/object.js +3 -2
- package/lib/timer.js +14 -10
- package/lib/validator.js +83 -82
- package/package.json +8 -9
package/lib/event.js
CHANGED
|
@@ -1,159 +1,568 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
*
|
|
6
|
-
*/
|
|
7
|
-
class Event
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
1
|
+
require('./global.js');
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* 高性能事件发射器
|
|
5
|
+
* 优化特殊事件存储,提高查找效率
|
|
6
|
+
*/
|
|
7
|
+
class Event {
|
|
8
|
+
static config = {
|
|
9
|
+
max_listeners: 100,
|
|
10
|
+
auto_clean: true,
|
|
11
|
+
error_handler: null
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* 构造函数
|
|
16
|
+
* @param {object} config 配置参数
|
|
17
|
+
*/
|
|
18
|
+
constructor(config) {
|
|
19
|
+
this.config = {
|
|
20
|
+
...Event.config,
|
|
21
|
+
...config || {}
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
// 事件存储结构优化
|
|
25
|
+
this._events = {
|
|
26
|
+
// 主事件(没有冒号的事件)
|
|
27
|
+
main: new Map(),
|
|
28
|
+
// 特殊事件分类存储
|
|
29
|
+
special: {
|
|
30
|
+
before: new Map(),
|
|
31
|
+
check: new Map(),
|
|
32
|
+
after: new Map(),
|
|
33
|
+
error: new Map(),
|
|
34
|
+
render: new Map(),
|
|
35
|
+
success: new Map(),
|
|
36
|
+
other: new Map()
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
// 事件计数器
|
|
41
|
+
this._counters = {
|
|
42
|
+
main: 0,
|
|
43
|
+
special: 0
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
// 日志对象
|
|
47
|
+
this._logger = $.log || console;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* 判断事件类型
|
|
52
|
+
* @param {string} event_name 事件名称
|
|
53
|
+
* @returns {string} 事件类型
|
|
54
|
+
* @private
|
|
55
|
+
*/
|
|
56
|
+
_getEventType(event_name) {
|
|
57
|
+
if (typeof event_name !== 'string') return 'main';
|
|
58
|
+
|
|
59
|
+
const parts = event_name.split(':');
|
|
60
|
+
if (parts.length < 2) return 'main';
|
|
61
|
+
|
|
62
|
+
const suffix = parts[parts.length - 1];
|
|
63
|
+
const special_types = ['before', 'check', 'after', 'error', 'render', 'success'];
|
|
64
|
+
|
|
65
|
+
if (special_types.includes(suffix)) {
|
|
66
|
+
return suffix;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return 'other';
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* 获取事件存储位置
|
|
74
|
+
* @param {string} event_name 事件名称
|
|
75
|
+
* @returns {object} 存储位置信息
|
|
76
|
+
* @private
|
|
77
|
+
*/
|
|
78
|
+
_getEventStore(event_name) {
|
|
79
|
+
const event_type = this._getEventType(event_name);
|
|
80
|
+
|
|
81
|
+
if (event_type === 'main') {
|
|
82
|
+
return {
|
|
83
|
+
map: this._events.main,
|
|
84
|
+
type: 'main'
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return {
|
|
89
|
+
map: this._events.special[event_type],
|
|
90
|
+
type: 'special',
|
|
91
|
+
special_type: event_type
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* 添加事件监听器
|
|
97
|
+
* @param {string} event_name 事件名称
|
|
98
|
+
* @param {function} listener 监听器函数
|
|
99
|
+
* @returns {Event} 返回this,支持链式调用
|
|
100
|
+
*/
|
|
101
|
+
on(event_name, listener) {
|
|
102
|
+
if (typeof listener !== 'function') {
|
|
103
|
+
throw new TypeError('监听器必须是函数');
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const store = this._getEventStore(event_name);
|
|
107
|
+
|
|
108
|
+
if (!store.map.has(event_name)) {
|
|
109
|
+
store.map.set(event_name, []);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const listeners = store.map.get(event_name);
|
|
113
|
+
|
|
114
|
+
// 检查监听器数量限制
|
|
115
|
+
if (listeners.length >= this.config.max_listeners) {
|
|
116
|
+
this._logger.warn(`事件 ${event_name} 的监听器数量已达到上限 ${this.config.max_listeners}`);
|
|
117
|
+
return this;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
listeners.push(listener);
|
|
121
|
+
|
|
122
|
+
// 更新计数器
|
|
123
|
+
if (store.type === 'special') {
|
|
124
|
+
this._counters.special++;
|
|
125
|
+
} else {
|
|
126
|
+
this._counters.main++;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return this;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* 添加一次性事件监听器
|
|
134
|
+
* @param {string} event_name 事件名称
|
|
135
|
+
* @param {function} listener 监听器函数
|
|
136
|
+
* @returns {Event} 返回this,支持链式调用
|
|
137
|
+
*/
|
|
138
|
+
once(event_name, listener) {
|
|
139
|
+
const once_wrapper = (...args) => {
|
|
140
|
+
this.off(event_name, once_wrapper);
|
|
141
|
+
return listener(...args);
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
once_wrapper._original = listener;
|
|
145
|
+
return this.on(event_name, once_wrapper);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* 移除事件监听器(removeListener 别名)
|
|
150
|
+
* @param {string} event_name 事件名称
|
|
151
|
+
* @param {function} listener 监听器函数
|
|
152
|
+
* @returns {Event} 返回this,支持链式调用
|
|
153
|
+
*/
|
|
154
|
+
removeListener(event_name, listener) {
|
|
155
|
+
return this.off(event_name, listener);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* 移除事件监听器
|
|
160
|
+
* @param {string} event_name 事件名称
|
|
161
|
+
* @param {function} listener 监听器函数
|
|
162
|
+
* @returns {Event} 返回this,支持链式调用
|
|
163
|
+
*/
|
|
164
|
+
off(event_name, listener) {
|
|
165
|
+
const store = this._getEventStore(event_name);
|
|
166
|
+
|
|
167
|
+
if (!store.map.has(event_name)) {
|
|
168
|
+
return this;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
const listeners = store.map.get(event_name);
|
|
172
|
+
|
|
173
|
+
if (listener) {
|
|
174
|
+
// 移除特定监听器
|
|
175
|
+
const index = listeners.findIndex(fn => fn === listener || fn._original === listener);
|
|
176
|
+
if (index !== -1) {
|
|
177
|
+
listeners.splice(index, 1);
|
|
178
|
+
|
|
179
|
+
// 更新计数器
|
|
180
|
+
if (store.type === 'special') {
|
|
181
|
+
this._counters.special--;
|
|
182
|
+
} else {
|
|
183
|
+
this._counters.main--;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
} else {
|
|
187
|
+
// 移除所有监听器
|
|
188
|
+
const count = listeners.length;
|
|
189
|
+
store.map.delete(event_name);
|
|
190
|
+
|
|
191
|
+
// 更新计数器
|
|
192
|
+
if (store.type === 'special') {
|
|
193
|
+
this._counters.special -= count;
|
|
194
|
+
} else {
|
|
195
|
+
this._counters.main -= count;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// 自动清理空的事件列表
|
|
200
|
+
if (this.config.auto_clean && listeners && listeners.length === 0) {
|
|
201
|
+
store.map.delete(event_name);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
return this;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* 触发事件
|
|
209
|
+
* @param {string} event_name 事件名称
|
|
210
|
+
* @param {...any} args 事件参数
|
|
211
|
+
* @returns {boolean} 是否成功触发事件
|
|
212
|
+
*/
|
|
213
|
+
emit(event_name, ...args) {
|
|
214
|
+
const store = this._getEventStore(event_name);
|
|
215
|
+
|
|
216
|
+
if (!store.map.has(event_name)) {
|
|
217
|
+
return false;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
const listeners = store.map.get(event_name).slice();
|
|
221
|
+
|
|
222
|
+
for (const listener of listeners) {
|
|
223
|
+
try {
|
|
224
|
+
listener(...args);
|
|
225
|
+
} catch (error) {
|
|
226
|
+
this._handleError(error, event_name, args);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
return true;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* 异步触发事件,按顺序执行等待完成
|
|
235
|
+
* @param {string} event_name 事件名称
|
|
236
|
+
* @param {...any} args 事件参数
|
|
237
|
+
* @returns {Promise} 事件触发结果
|
|
238
|
+
*/
|
|
239
|
+
async emitWait(event_name, ...args) {
|
|
240
|
+
const store = this._getEventStore(event_name);
|
|
241
|
+
|
|
242
|
+
if (!store.map.has(event_name)) {
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
const listeners = store.map.get(event_name).slice();
|
|
247
|
+
|
|
248
|
+
for (const listener of listeners) {
|
|
249
|
+
try {
|
|
250
|
+
await listener(...args);
|
|
251
|
+
} catch (error) {
|
|
252
|
+
this._handleError(error, event_name, args);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* 异步触发事件,并发执行不等待
|
|
259
|
+
* @param {string} event_name 事件名称
|
|
260
|
+
* @param {...any} args 事件参数
|
|
261
|
+
* @returns {boolean} 是否成功触发事件
|
|
262
|
+
*/
|
|
263
|
+
emitAsync(event_name, ...args) {
|
|
264
|
+
const store = this._getEventStore(event_name);
|
|
265
|
+
|
|
266
|
+
if (!store.map.has(event_name)) {
|
|
267
|
+
return false;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
const listeners = store.map.get(event_name).slice();
|
|
271
|
+
|
|
272
|
+
listeners.forEach(listener => {
|
|
273
|
+
try {
|
|
274
|
+
Promise.resolve(listener(...args))
|
|
275
|
+
.catch(error => {
|
|
276
|
+
this._handleError(error, event_name, args);
|
|
277
|
+
});
|
|
278
|
+
} catch (sync_error) {
|
|
279
|
+
this._handleError(sync_error, event_name, args);
|
|
280
|
+
}
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
return true;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* 异步触发事件,并发执行等待完成
|
|
288
|
+
* @param {string} event_name 事件名称
|
|
289
|
+
* @param {...any} args 事件参数
|
|
290
|
+
* @returns {Promise} 事件触发结果
|
|
291
|
+
*/
|
|
292
|
+
async emitAll(event_name, ...args) {
|
|
293
|
+
const store = this._getEventStore(event_name);
|
|
294
|
+
|
|
295
|
+
if (!store.map.has(event_name)) {
|
|
296
|
+
return [];
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
const listeners = store.map.get(event_name).slice();
|
|
300
|
+
const promises = listeners.map(listener => {
|
|
301
|
+
try {
|
|
302
|
+
return Promise.resolve(listener(...args));
|
|
303
|
+
} catch (error) {
|
|
304
|
+
return Promise.reject(error);
|
|
305
|
+
}
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
return await Promise.all(promises);
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* 异步触发事件,竞争执行
|
|
313
|
+
* @param {string} event_name 事件名称
|
|
314
|
+
* @param {...any} args 事件参数
|
|
315
|
+
* @returns {Promise} 第一个完成的结果
|
|
316
|
+
*/
|
|
317
|
+
async emitRace(event_name, ...args) {
|
|
318
|
+
const store = this._getEventStore(event_name);
|
|
319
|
+
|
|
320
|
+
if (!store.map.has(event_name)) {
|
|
321
|
+
return null;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
const listeners = store.map.get(event_name).slice();
|
|
325
|
+
const promises = listeners.map((listener, index) =>
|
|
326
|
+
Promise.resolve(listener(...args))
|
|
327
|
+
.then(result => ({ index, result, status: 'fulfilled' }))
|
|
328
|
+
.catch(error => ({ index, error, status: 'rejected' }))
|
|
329
|
+
);
|
|
330
|
+
|
|
331
|
+
return await Promise.race(promises);
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
/**
|
|
335
|
+
* 异步触发事件,瀑布流执行
|
|
336
|
+
* @param {string} event_name 事件名称
|
|
337
|
+
* @param {*} value 初始值
|
|
338
|
+
* @param {...any} args 事件参数
|
|
339
|
+
* @returns {Promise} 最后一个事件监听者的结果
|
|
340
|
+
*/
|
|
341
|
+
async emitWaterfall(event_name, value, ...args) {
|
|
342
|
+
const store = this._getEventStore(event_name);
|
|
343
|
+
|
|
344
|
+
if (!store.map.has(event_name)) {
|
|
345
|
+
return value;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
const listeners = store.map.get(event_name).slice();
|
|
349
|
+
let val = value;
|
|
350
|
+
|
|
351
|
+
for (const listener of listeners) {
|
|
352
|
+
try {
|
|
353
|
+
val = await listener(val, ...args);
|
|
354
|
+
} catch (error) {
|
|
355
|
+
this._handleError(error, event_name, args);
|
|
356
|
+
throw error;
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
return val;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
/**
|
|
364
|
+
* 获取事件监听器数量
|
|
365
|
+
* @param {string} event_name 事件名称
|
|
366
|
+
* @returns {number} 监听器数量
|
|
367
|
+
*/
|
|
368
|
+
listenerCount(event_name) {
|
|
369
|
+
const store = this._getEventStore(event_name);
|
|
370
|
+
|
|
371
|
+
if (!store.map.has(event_name)) {
|
|
372
|
+
return 0;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
return store.map.get(event_name).length;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
/**
|
|
379
|
+
* 获取所有事件监听器
|
|
380
|
+
* @param {string} event_name 事件名称
|
|
381
|
+
* @returns {array} 监听器数组
|
|
382
|
+
*/
|
|
383
|
+
listeners(event_name) {
|
|
384
|
+
const store = this._getEventStore(event_name);
|
|
385
|
+
|
|
386
|
+
if (!store.map.has(event_name)) {
|
|
387
|
+
return [];
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
return store.map.get(event_name).slice();
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
/**
|
|
394
|
+
* 移除所有事件监听器
|
|
395
|
+
* @param {string} event_name 事件名称,不传则移除所有事件
|
|
396
|
+
* @returns {Event} 返回this,支持链式调用
|
|
397
|
+
*/
|
|
398
|
+
removeAllListeners(event_name) {
|
|
399
|
+
if (event_name) {
|
|
400
|
+
const store = this._getEventStore(event_name);
|
|
401
|
+
|
|
402
|
+
if (store.map.has(event_name)) {
|
|
403
|
+
const count = store.map.get(event_name).length;
|
|
404
|
+
store.map.delete(event_name);
|
|
405
|
+
|
|
406
|
+
// 更新计数器
|
|
407
|
+
if (store.type === 'special') {
|
|
408
|
+
this._counters.special -= count;
|
|
409
|
+
} else {
|
|
410
|
+
this._counters.main -= count;
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
} else {
|
|
414
|
+
// 移除所有事件
|
|
415
|
+
this._events.main.clear();
|
|
416
|
+
Object.values(this._events.special).forEach(map => map.clear());
|
|
417
|
+
this._counters.main = 0;
|
|
418
|
+
this._counters.special = 0;
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
return this;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
/**
|
|
425
|
+
* 获取所有事件名称
|
|
426
|
+
* @returns {array} 事件名称数组
|
|
427
|
+
*/
|
|
428
|
+
eventNames() {
|
|
429
|
+
const event_names = [];
|
|
430
|
+
|
|
431
|
+
// 添加 main 类型事件
|
|
432
|
+
for (const event_name of this._events.main.keys()) {
|
|
433
|
+
event_names.push(event_name);
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
// 添加特殊类型事件
|
|
437
|
+
for (const [type, map] of Object.entries(this._events.special)) {
|
|
438
|
+
for (const event_name of map.keys()) {
|
|
439
|
+
event_names.push(event_name);
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
return event_names;
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
/**
|
|
447
|
+
* 前置添加事件监听器
|
|
448
|
+
* @param {string} event_name 事件名称
|
|
449
|
+
* @param {function} listener 监听器函数
|
|
450
|
+
* @returns {Event} 返回this,支持链式调用
|
|
451
|
+
*/
|
|
452
|
+
prependListener(event_name, listener) {
|
|
453
|
+
if (typeof listener !== 'function') {
|
|
454
|
+
throw new TypeError('监听器必须是函数');
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
const store = this._getEventStore(event_name);
|
|
458
|
+
|
|
459
|
+
if (!store.map.has(event_name)) {
|
|
460
|
+
store.map.set(event_name, []);
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
const listeners = store.map.get(event_name);
|
|
464
|
+
|
|
465
|
+
// 检查监听器数量限制
|
|
466
|
+
if (listeners.length >= this.config.max_listeners) {
|
|
467
|
+
this._logger.warn(`事件 ${event_name} 的监听器数量已达到上限 ${this.config.max_listeners}`);
|
|
468
|
+
return this;
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
// 前置添加监听器
|
|
472
|
+
listeners.unshift(listener);
|
|
473
|
+
|
|
474
|
+
// 更新计数器
|
|
475
|
+
if (store.type === 'special') {
|
|
476
|
+
this._counters.special++;
|
|
477
|
+
} else {
|
|
478
|
+
this._counters.main++;
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
return this;
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
/**
|
|
485
|
+
* 前置添加一次性事件监听器
|
|
486
|
+
* @param {string} event_name 事件名称
|
|
487
|
+
* @param {function} listener 监听器函数
|
|
488
|
+
* @returns {Event} 返回this,支持链式调用
|
|
489
|
+
*/
|
|
490
|
+
prependOnceListener(event_name, listener) {
|
|
491
|
+
const once_wrapper = (...args) => {
|
|
492
|
+
this.off(event_name, once_wrapper);
|
|
493
|
+
return listener(...args);
|
|
494
|
+
};
|
|
495
|
+
|
|
496
|
+
once_wrapper._original = listener;
|
|
497
|
+
return this.prependListener(event_name, once_wrapper);
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
/**
|
|
501
|
+
* 获取原始监听器数组
|
|
502
|
+
* @param {string} event_name 事件名称
|
|
503
|
+
* @returns {array} 原始监听器数组
|
|
504
|
+
*/
|
|
505
|
+
rawListeners(event_name) {
|
|
506
|
+
const store = this._getEventStore(event_name);
|
|
507
|
+
|
|
508
|
+
if (!store.map.has(event_name)) {
|
|
509
|
+
return [];
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
return store.map.get(event_name).slice();
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
/**
|
|
516
|
+
* 获取事件统计信息
|
|
517
|
+
* @returns {object} 统计信息
|
|
518
|
+
*/
|
|
519
|
+
getStats() {
|
|
520
|
+
return {
|
|
521
|
+
total: this._counters.main + this._counters.special,
|
|
522
|
+
main: this._counters.main,
|
|
523
|
+
special: this._counters.special,
|
|
524
|
+
special_types: {
|
|
525
|
+
before: this._events.special.before.size,
|
|
526
|
+
check: this._events.special.check.size,
|
|
527
|
+
after: this._events.special.after.size,
|
|
528
|
+
error: this._events.special.error.size,
|
|
529
|
+
render: this._events.special.render.size,
|
|
530
|
+
success: this._events.special.success.size,
|
|
531
|
+
other: this._events.special.other.size
|
|
532
|
+
}
|
|
533
|
+
};
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
/**
|
|
537
|
+
* 错误处理
|
|
538
|
+
* @param {Error} error 错误对象
|
|
539
|
+
* @param {string} event_name 事件名称
|
|
540
|
+
* @param {array} args 事件参数
|
|
541
|
+
* @private
|
|
542
|
+
*/
|
|
543
|
+
_handleError(error, event_name, args) {
|
|
544
|
+
if (this.config.error_handler) {
|
|
545
|
+
try {
|
|
546
|
+
this.config.error_handler(error, event_name, args);
|
|
547
|
+
} catch (handler_error) {
|
|
548
|
+
this._logger.error('错误处理函数执行失败:', handler_error);
|
|
549
|
+
}
|
|
550
|
+
} else {
|
|
551
|
+
this._logger.error(`事件 ${event_name} 执行失败:`, error);
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
/**
|
|
556
|
+
* 日志输出
|
|
557
|
+
* @param {string} level 日志级别
|
|
558
|
+
* @param {string} message 日志消息
|
|
559
|
+
* @param {...any} args 日志参数
|
|
560
|
+
*/
|
|
561
|
+
log(level, message, ...args) {
|
|
562
|
+
this._logger[level](`[${this.constructor.name}] ${message}`, ...args);
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
module.exports = {
|
|
567
|
+
Event
|
|
568
|
+
};
|