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/event.js CHANGED
@@ -1,159 +1,568 @@
1
- const emitter = require('events');
2
- require('./global.js');
3
-
4
- /**
5
- * 事件类
6
- */
7
- class Event extends emitter {
8
- /**
9
- *
10
- */
11
- constructor() {
12
- super();
13
- // 日志对象
14
- this._logger = $.log || console;
15
- }
16
- }
17
-
18
- /**
19
- * 日志输出
20
- * @param {string} level 日志级别
21
- * @param {string} message 日志消息
22
- * @param {...any} args 日志参数
23
- */
24
- Event.prototype.log = function (level, message, ...args) {
25
- this._logger[level](`[${this.constructor.name}] ${message}`, ...args);
26
- };
27
-
28
- /**
29
- * 异步触发事件,按顺序执行等待完成
30
- * @param {string} event 事件名称
31
- * @param {...any} args 事件参数
32
- * @returns {Promise} - 事件触发结果
33
- */
34
- Event.prototype.emitWait = async function (event, ...args) {
35
- const listeners = this.listeners(event);
36
- if (listeners.length === 0) {
37
- return;
38
- } else {
39
- for (const listener of listeners) {
40
- try {
41
- await listener(...args);
42
- } catch (err) {
43
- this.log('error', 'Error in async event listener:', err);
44
- }
45
- }
46
- }
47
- };
48
-
49
- /**
50
- * 异步触发事件,并发执行不等待
51
- * @param {string} event 事件名称
52
- * @param {...any} args 事件参数
53
- * @returns {boolean} 是否成功触发事件
54
- */
55
- Event.prototype.emitAsync = async function (event, ...args) {
56
- const listeners = this.listeners(event);
57
-
58
- if (listeners.length === 0) {
59
- return false;
60
- }
61
-
62
- // 立即启动所有监听器,但不等待
63
- listeners.forEach(listener => {
64
- try {
65
- // 使用 Promise.resolve 确保异步执行
66
- Promise.resolve(listener(...args))
67
- .catch(error => {
68
- // 错误处理 - 记录但不抛出
69
- this.log('error', `Async listener error for event ${event}:`, error);
70
- this.emit('async:error', error, event, args);
71
- });
72
- } catch (syncError) {
73
- // 同步错误处理
74
- this.log('error', `Sync listener error for event ${event}:`, syncError);
75
- this.emit('sync:error', syncError, event, args);
76
- }
77
- });
78
-
79
- return true;
80
- };
81
-
82
- /**
83
- * 异步触发事件,并发执行等待完成
84
- * @param {string} event 事件名称
85
- * @param {...any} args 事件参数
86
- * @returns {Promise} - 事件触发结果
87
- */
88
- Event.prototype.emitAll = async function (event, ...args) {
89
- const listeners = this.listeners(event);
90
-
91
- if (listeners.length === 0) {
92
- return [];
93
- }
94
-
95
- const promises = listeners.map(listener => {
96
- try {
97
- return Promise.resolve(listener(...args));
98
- } catch (error) {
99
- return Promise.reject(error);
100
- }
101
- });
102
-
103
- return await Promise.all(promises);
104
- };
105
-
106
- /**
107
- * 异步触发事件,竞争执行
108
- * @param {string} event 事件名称
109
- * @param {...any} args 事件参数
110
- * @returns {Promise} - 第一个完成的结果
111
- */
112
- Event.prototype.emitRace = async function (event, ...args) {
113
- const listeners = this.listeners(event);
114
-
115
- if (listeners.length === 0) {
116
- return null;
117
- }
118
-
119
- const promises = listeners.map((listener, index) =>
120
- Promise.resolve(listener(...args))
121
- .then(result => ({ index, result, status: 'fulfilled' }))
122
- .catch(error => ({ index, error, status: 'rejected' }))
123
- );
124
-
125
- // 使用 Promise.race 获取第一个完成的结果
126
- return await Promise.race(promises);
127
- };
128
-
129
- /**
130
- * 异步触发事件,瀑布流执行
131
- * @param {string} event 事件名称
132
- * @param {*} value 初始值
133
- * @param {...any} args 事件参数
134
- * @returns {Promise} - 最后一个事件监听者的结果
135
- */
136
- Event.prototype.emitWaterfall = async function (event, value, ...args) {
137
- const listeners = this.listeners(event);
138
-
139
- if (listeners.length === 0) {
140
- return value;
141
- }
142
-
143
- let val = value;
144
-
145
- for (const listener of listeners) {
146
- try {
147
- val = await listener(val, ...args);
148
- } catch (error) {
149
- this.log('error', 'Waterfall execution failed:', error);
150
- throw error;
151
- }
152
- }
153
-
154
- return val;
155
- };
156
-
157
- module.exports = {
158
- Event
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
+ };