mm_expand 2.4.1 → 2.4.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/eventer.js CHANGED
@@ -1,2406 +1,2294 @@
1
- /* eslint-disable mm_eslint/function-name */
2
- require('./global.js');
3
-
4
- /**
5
- * 事件类 - 增强版EventBus实现
6
- */
7
- class Eventer {
8
- static config = {
9
- max_list: 10, // 最大监听器数量
10
- default_name: 'default', // 默认命名空间
11
- chain_enabled: true, // 是否启用链式触发
12
- auto_clean: true, // 是否自动清理空的事件列表
13
- error: null, // 全局错误处理函数
14
- pause_enabled: true, // 是否启用暂停功能
15
- };
16
-
17
- // 日志对象
18
- #logger = $.log || console;
19
-
20
- /**
21
- * 构造函数
22
- * @param {object} config 配置参数
23
- */
24
- constructor(config) {
25
- this.config = {
26
- ...Eventer.config,
27
- ...config || {}
28
- };
29
- // 是否为插件
30
- this.is_plugin = false;
31
- // 事件字典 - 支持命名空间
32
- this._dict = {};
33
- // 事件中间件
34
- this._middleware = [];
35
- // 命名空间映射
36
- this._space = {};
37
- // 事件链映射 { 'event1': ['event2', 'event3'], 'space:event1': ['event4'] }
38
- this._chain = {};
39
- // 进行中的任务映射,用于取消操作
40
- this._tasks = new Map();
41
- // 暂停状态管理
42
- this._paused = new Set(); // 暂停的单个事件
43
- this._paused_space = new Set(); // 暂停的命名空间
44
- this._paused_global = false; // 全局暂停状态
45
- // 初始化默认命名空间
46
- this._space[this.config.default_name] = true;
47
- }
48
-
49
- /**
50
- * 设置日志记录器
51
- * @param {object} logger 日志记录器对象
52
- */
53
- setLogger(logger) {
54
- this.#logger = logger;
55
- }
56
-
57
- /**
58
- * 获取日志记录器
59
- * @returns {object} 日志记录器对象
60
- */
61
- getLogger() {
62
- return this.#logger;
63
- }
64
-
65
- /**
66
- * 日志输出
67
- * @param {string} level 日志级别
68
- * @param {string} message 日志消息
69
- * @param {...any} params 日志参数
70
- */
71
- log(level, message, ...params) {
72
- this.getLogger()[level](`[${this.constructor.name}] ${message}`, ...params);
73
- };
74
- }
75
-
76
- /**
77
- * 初始化事件管理器
78
- * @param {...any} args 初始化参数
79
- * @returns {Eventer} 返回事件管理器实例
80
- * @private
81
- */
82
- Eventer.prototype._init = async function (...args) {
83
- // 初始化逻辑
84
- return this;
85
- };
86
-
87
- /**
88
- * 初始化事件管理器
89
- * @param {...any} args 初始化参数
90
- * @returns {Eventer} 返回事件管理器实例
91
- */
92
- Eventer.prototype.init = async function (...args) {
93
- return this._init(...args);
94
- };
95
-
96
- /**
97
- * 监听事件(支持命名空间和优先级)
98
- * @param {string} key 事件关键字,支持space:key格式
99
- * @param {object} func 触发函数
100
- * @throws {Error} 事件关键字必须是非空字符串
101
- * @throws {Error} 事件处理函数必须是一个函数
102
- */
103
- Eventer.prototype._validateOnParams = function (key, func) {
104
- if (!key || typeof key !== 'string') {
105
- throw new Error('事件关键字必须是非空字符串');
106
- }
107
- if (typeof func !== 'function') {
108
- throw new Error('事件处理函数必须是一个函数');
109
- }
110
- };
111
-
112
- Eventer.prototype._parseEventKey = function (key, ns) {
113
- let parsed = this._parseKey(key);
114
- let space = ns || parsed.space;
115
- let event_key = parsed.key;
116
- let full_key = `${space}:${event_key}`;
117
- return { space, event_key, full_key };
118
- };
119
-
120
- Eventer.prototype._initNamespace = function (space, event_key) {
121
- if (!this._dict[space]) {
122
- this._dict[space] = {};
123
- this._space[space] = true;
124
- }
125
- if (!this._dict[space][event_key]) {
126
- this._dict[space][event_key] = [];
127
- }
128
- };
129
-
130
- Eventer.prototype._generateDefaultName = function (func) {
131
- return func.name || `handler_${Date.now()}_${Math.floor(Math.random() * 1000)}`;
132
- };
133
-
134
- Eventer.prototype._wrapFunction = function (func, params) {
135
- let wrapped_func = func;
136
-
137
- if (params.throttle) {
138
- wrapped_func = this._throttle(func, params.throttle);
139
- } else if (params.debounce) {
140
- wrapped_func = this._debounce(func, params.debounce);
141
- }
142
-
143
- if (params.timeout && typeof params.timeout === 'number' && params.timeout > 0) {
144
- let original_func = wrapped_func;
145
- wrapped_func = async function (...args) {
146
- const timeoutPromise = new Promise((resolve, reject) => {
147
- setTimeout(() => reject(new Error(`事件执行超时 (${params.timeout}ms)`)), params.timeout);
148
- });
149
- return Promise.race([original_func.apply(this, args), timeoutPromise]);
150
- };
151
- }
152
-
153
- return wrapped_func;
154
- };
155
-
156
- Eventer.prototype._createHandlerObj = function (config) {
157
- var handler = {
158
- name: config.name,
159
- func: config.wrapped_func,
160
- original_func: config.func,
161
- times: config.times,
162
- priority: config.priority,
163
- created_at: Date.now(),
164
- last_executed: null
165
- };
166
- return handler;
167
- };
168
-
169
- Eventer.prototype._findHandlerIndex = function (list, name) {
170
- for (let i = 0; i < list.length; i++) {
171
- if (list[i].name === name) {
172
- return i;
173
- }
174
- }
175
- return -1;
176
- };
177
-
178
- Eventer.prototype._checkListenerLimit = function (space, event_key, list) {
179
- let max_list = this.config.max_list;
180
- if (max_list > 0 && list.length >= max_list) {
181
- this.log('warn', `警告: '${space}:${event_key}' 事件的监听器数量已达到 ${max_list},可能导致内存泄漏。使用 set_max_listeners() 方法可以增加限制。`);
182
- }
183
- };
184
-
185
- Eventer.prototype._createHandlerResult = function (space, index, name, full_key) {
186
- return {
187
- space,
188
- index,
189
- name,
190
- remove: () => this.off(full_key, name)
191
- };
192
- };
193
-
194
- /**
195
- * 监听事件(支持命名空间和优先级)
196
- * @param {string} key 事件关键字,支持space:key格式
197
- * @param {object} func 触发函数
198
- * @param {string} name 增加名称,方便删除,当出现相同名称时会被覆盖
199
- * @param {object} options 其他选项,如throttle、debounce、timeout等
200
- * @returns {object} 返回事件信息对象 {space, index, name, remove},remove为移除该事件的函数
201
- */
202
- Eventer.prototype.on = function (key, func, name, options) {
203
- // 处理参数
204
- let params = this._processOnParams(key, func, name, options);
205
-
206
- // 验证参数
207
- this._validateOnParams(params.key, params.func);
208
-
209
- // 处理事件添加
210
- return this._addEventHandler(params);
211
- };
212
-
213
- Eventer.prototype._processOnParams = function (key, func, name, options) {
214
- // 支持两种调用方式:便捷方式和配置对象方式
215
- if (typeof key === 'object' && key !== null) {
216
- // 配置对象方式
217
- return this._extractOnParams(key);
218
- } else {
219
- // 便捷方式
220
- let opts = options || {};
221
- return {
222
- key: key,
223
- func: func,
224
- name: name,
225
- times: opts.times || -1,
226
- priority: opts.priority || 0,
227
- ns: opts.ns || null
228
- };
229
- }
230
- };
231
-
232
- Eventer.prototype._addEventHandler = function (params) {
233
- const { key: eventKey, func: eventFunc, name: eventName,
234
- times: eventTimes, priority: eventPriority, ns } = params;
235
-
236
- // 解析命名空间
237
- const { space, event_key, full_key } = this._parseEventKey(eventKey, ns);
238
-
239
- // 初始化命名空间和事件数组
240
- this._initNamespace(space, event_key);
241
-
242
- // 设置默认名称
243
- let final_name = eventName || this._generateDefaultName(eventFunc);
244
-
245
- // 应用节流或防抖
246
- let wrapped_func = this._wrapFunction(eventFunc, params);
247
-
248
- // 创建事件对象
249
- let obj = this._createHandlerObj({
250
- name: final_name,
251
- wrapped_func: wrapped_func,
252
- func: eventFunc,
253
- times: eventTimes,
254
- priority: eventPriority
255
- });
256
-
257
- // 处理事件添加逻辑
258
- return this._handleEventAddition({ space, event_key, full_key, final_name, obj });
259
- };
260
-
261
- Eventer.prototype._extractOnParams = function (config) {
262
- return {
263
- key: config.key,
264
- func: config.func,
265
- name: config.name,
266
- times: config.times || -1,
267
- priority: config.priority || 0,
268
- ns: config.ns || null
269
- };
270
- };
271
-
272
- Eventer.prototype._processOnceParams = function (key, func, name, options) {
273
- // 支持两种调用方式:便捷方式和配置对象方式
274
- if (typeof key === 'object' && key !== null) {
275
- // 配置对象方式
276
- let params = this._extractOnParams(key);
277
- params.times = 1; // 强制设置为仅执行一次
278
- return params;
279
- } else {
280
- // 便捷方式
281
- let opts = options || {};
282
- return {
283
- key: key,
284
- func: func,
285
- name: name,
286
- times: 1, // 强制设置为仅执行一次
287
- priority: opts.priority || 0,
288
- ns: opts.ns || null
289
- };
290
- }
291
- };
292
-
293
- Eventer.prototype._handleEventAddition = function (config) {
294
- const { space, event_key, full_key, final_name, obj } = config;
295
- let list = this._dict[space][event_key];
296
- let idx = this._findHandlerIndex(list, final_name);
297
-
298
- if (idx >= 0) {
299
- // 覆盖已存在的同名监听器
300
- Object.assign(list[idx], obj);
301
- // 重新排序
302
- this._sort(list);
303
- return this._createHandlerResult(space, idx, final_name, full_key);
304
- } else {
305
- // 检查监听器数量是否超过限制
306
- this._checkListenerLimit(space, event_key, list);
307
-
308
- // 添加新事件
309
- list.push(obj);
310
- // 按优先级排序
311
- this._sort(list);
312
- return this._createHandlerResult(space, list.length - 1, final_name, full_key);
313
- }
314
- };
315
-
316
- /**
317
- * 监听事件(仅执行一次)
318
- * @param {string | object} key 事件关键,支持space:key格式,或配置对象
319
- * @param {object} func 触发函数
320
- * @param {string} name 增加名称,方便删除,当出现相同名称时会被覆盖
321
- * @param {object} options 其他选项
322
- * @returns {object} 返回事件信息对象 {space, idx, name}
323
- */
324
- Eventer.prototype.once = function (key, func, name, options) {
325
- // 处理参数
326
- let params = this._processOnceParams(key, func, name, options);
327
-
328
- // 验证参数
329
- this._validateOnParams(params.key, params.func);
330
-
331
- // 处理事件添加
332
- return this._addEventHandler(params);
333
- };
334
-
335
- /**
336
- * 统一的事件执行引擎
337
- * @param {string} key 事件关键字,支持space:key格式
338
- * @throws {Error} 事件关键字必须是非空字符串
339
- * @private
340
- */
341
- Eventer.prototype._validateExec = function (key) {
342
- if (!key || typeof key !== 'string') {
343
- throw new Error('事件关键字必须是非空字符串');
344
- }
345
- };
346
-
347
- Eventer.prototype._createCtx = function (key, params) {
348
- let parsed = this._parseKey(key);
349
- let space = parsed.space;
350
- let event_key = parsed.key;
351
- let full_key = `${space}:${event_key}`;
352
- let start_time = Date.now();
353
-
354
- const ctx = {
355
- space,
356
- event: event_key,
357
- full_event: full_key,
358
- params,
359
- results: [],
360
- start_time: start_time,
361
- executed: 0,
362
- error_count: 0,
363
- cancelled: false,
364
- cancel: () => {
365
- ctx.cancelled = true;
366
- this._cancelTasks(full_key);
367
- }
368
- };
369
-
370
- return { ctx, space, event_key, full_key, start_time };
371
- };
372
-
373
- Eventer.prototype._cancelTasks = function (full_key) {
374
- try {
375
- if (this._tasks.has(full_key)) {
376
- let tasks = this._tasks.get(full_key);
377
- tasks.forEach(task => {
378
- if (task && typeof task.cancel === 'function') {
379
- try {
380
- task.cancel();
381
- } catch (cancel_error) {
382
- this.log('error', `任务取消失败 [${full_key}] - ${task.id}`, cancel_error);
383
- }
384
- }
385
- });
386
- this._tasks.delete(full_key);
387
- }
388
- } catch (cancel_global_error) {
389
- this.log('error', `任务取消过程异常 [${full_key}]`, cancel_global_error);
390
- }
391
- };
392
-
393
- Eventer.prototype._initTaskList = function (full_key) {
394
- try {
395
- this._tasks.set(full_key, []);
396
- } catch (task_init_error) {
397
- this.log('error', `任务列表初始化失败 [${full_key}]`, task_init_error);
398
- }
399
- };
400
-
401
- Eventer.prototype._runBeforeMiddleware = async function (ctx, full_key) {
402
- try {
403
- await this._runMiddleware('before', ctx);
404
- if (ctx.cancelled) {
405
- this._cleanupTasks(full_key);
406
- return true;
407
- }
408
- return false;
409
- } catch (error) {
410
- this.log('error', `事件中间件执行失败 [${ctx.space}:${ctx.event}]`, error);
411
- if (this.config.error_handler && typeof this.config.error_handler === 'function') {
412
- this.config.error_handler(error, { type: 'middleware', stage: 'before', ctx });
413
- }
414
- return false;
415
- }
416
- };
417
-
418
- Eventer.prototype._cleanupTasks = function (full_key) {
419
- try {
420
- this._tasks.delete(full_key);
421
- } catch (cleanup_error) {
422
- this.log('error', `任务清理失败 [${full_key}]`, cleanup_error);
423
- }
424
- };
425
-
426
- Eventer.prototype._executeStrategy = async function (config) {
427
- const { list, params, ctx, full_key, arr, options } = config;
428
-
429
- try {
430
- if (options.exec_mode === 'parallel') {
431
- await this._executeParallel({ list, params, ctx, full_key, arr });
432
- } else if (options.exec_mode === 'race') {
433
- ctx.race_result = await this._executeRace({ list, params, ctx, full_key, arr });
434
- } else if (options.exec_mode === 'waterfall') {
435
- await this._executeWaterfall({
436
- list, params, ctx, full_key, arr,
437
- initial_value: options.initial_value
438
- });
439
- } else {
440
- await this._executeSequential({ list, params, ctx, full_key, arr });
441
- }
442
- } catch (exec_error) {
443
- this.log('error', `事件执行策略异常 [${full_key}]`, exec_error);
444
- if (this.config.error_handler && typeof this.config.error_handler === 'function') {
445
- this.config.error_handler(exec_error, { type: 'execution', ctx });
446
- }
447
- }
448
- };
449
-
450
- Eventer.prototype._removeEvents = function (space, key, arr) {
451
- try {
452
- for (let i = 0; i < arr.length; i++) {
453
- this.del(`${space}:${key}`, arr[i]);
454
- }
455
- } catch (remove_error) {
456
- this.log('error', `事件移除失败 [${space}:${key}]`, remove_error);
457
- }
458
- };
459
-
460
- Eventer.prototype._autoCleanup = function (space, key) {
461
- try {
462
- if (this.config.auto_clean && this._dict[space] && this._dict[space][key] &&
463
- this._dict[space][key].length === 0) {
464
- delete this._dict[space][key];
465
- if (this._dict[space] && Object.keys(this._dict[space]).length === 0) {
466
- delete this._dict[space];
467
- delete this._space[space];
468
- }
469
- }
470
- } catch (cleanup_error) {
471
- this.log('error', `自动清理失败 [${space}:${key}]`, cleanup_error);
472
- }
473
- };
474
-
475
- Eventer.prototype._runAfterMiddleware = async function (ctx, start_time) {
476
- try {
477
- ctx.end_time = Date.now();
478
- ctx.duration = ctx.end_time - start_time;
479
- await this._runMiddleware('after', ctx);
480
- } catch (error) {
481
- this.log('error', `事件后置中间件执行失败 [${ctx.space}:${ctx.event}]`, error);
482
- if (this.config.error_handler && typeof this.config.error_handler === 'function') {
483
- this.config.error_handler(error, { type: 'middleware', stage: 'after', ctx });
484
- }
485
- }
486
- };
487
-
488
- Eventer.prototype._executeEventChain = async function (ctx, full_key, params) {
489
- if (!ctx.cancelled && this.config.chain_enabled && this._chain[full_key]) {
490
- try {
491
- await this._triggerChain(full_key, params);
492
- } catch (chain_error) {
493
- this.log('error', `事件链执行失败 [${full_key}]`, chain_error);
494
- if (this.config.error_handler && typeof this.config.error_handler === 'function') {
495
- this.config.error_handler(chain_error, { type: 'chain', ctx });
496
- }
497
- }
498
- }
499
- };
500
-
501
- Eventer.prototype._buildSafeResult = function (ctx) {
502
- try {
503
- return {
504
- results: ctx.results || [],
505
- cancelled: ctx.cancelled || false,
506
- cancel: ctx.cancel || (() => { }),
507
- race: ctx.race_result,
508
- waterfall: ctx.results && ctx.results.length > 0 ? ctx.results[ctx.results.length - 1]
509
- : undefined
510
- };
511
- } catch (return_error) {
512
- this.log('error', `结果构造失败 [${ctx.full_event}]`, return_error);
513
- return {
514
- results: [],
515
- cancelled: true,
516
- cancel: () => { },
517
- error: return_error
518
- };
519
- }
520
- };
521
-
522
- Eventer.prototype._execute = async function (key, options = {}, ...params) {
523
- this._validateExec(key);
524
-
525
- const { ctx, space, event_key, full_key, start_time } = this._createCtx(key, params);
526
-
527
- if (this.isPaused(full_key)) {
528
- return this._createPausedResult();
529
- }
530
-
531
- let list = this._dict[space] && this._dict[space][event_key];
532
- const arr = [];
533
-
534
- if (list && list.length > 0) {
535
- await this._executeEventList({
536
- list, params, ctx, full_key, arr, options, space, event_key, start_time
537
- });
538
- }
539
-
540
- await this._executeEventChain(ctx, full_key, params);
541
- return this._buildSafeResult(ctx);
542
- };
543
-
544
- /**
545
- * 创建暂停状态的结果对象
546
- * @returns {object} 暂停状态的结果
547
- * @private
548
- */
549
- Eventer.prototype._createPausedResult = function () {
550
- return {
551
- results: [],
552
- cancelled: false,
553
- paused: true,
554
- /**
555
- * 取消函数
556
- */
557
- cancel: () => { }
558
- };
559
- };
560
-
561
- /**
562
- * 执行事件列表
563
- * @param {object} config 配置参数
564
- * @param {Array} config.list 事件列表
565
- * @param {Array} config.params 参数
566
- * @param {object} config.ctx 上下文
567
- * @param {string} config.full_key 完整键名
568
- * @param {Array} config.arr 数组
569
- * @param {object} config.options 选项
570
- * @param {string} config.space 命名空间
571
- * @param {string} config.event_key 事件键
572
- * @param {number} config.start_time 开始时间
573
- * @param {string} config.strategy 执行策略,默认sequential
574
- * @returns {object} 返回执行结果
575
- * @private
576
- */
577
- Eventer.prototype._executeEventList = async function (config) {
578
- const { list, params, ctx, full_key, arr, options, space, event_key, start_time } = config;
579
-
580
- this._initTaskList(full_key);
581
-
582
- let cancelled = await this._runBeforeMiddleware(ctx, full_key);
583
- if (cancelled) {
584
- return {
585
- results: [],
586
- cancelled: true,
587
- cancel: ctx.cancel
588
- };
589
- }
590
-
591
- await this._executeStrategy({ list, params, ctx, full_key, arr, options });
592
-
593
- this._cleanupTasks(full_key);
594
- this._removeEvents(space, event_key, arr);
595
- this._autoCleanup(space, event_key);
596
- await this._runAfterMiddleware(ctx, start_time);
597
- };
598
-
599
- /**
600
- * 顺序执行事件处理函数
601
- * @param {object} config 配置参数
602
- * @private
603
- */
604
- Eventer.prototype._executeSequential = async function (config) {
605
- const { list, params, ctx, full_key, arr } = config;
606
-
607
- for (let i = 0; i < list.length && !ctx.cancelled; i++) {
608
- let o = list[i];
609
- ctx.executed++;
610
- o.last_executed = Date.now();
611
-
612
- // 创建并执行单个任务
613
- await this._execSingleTask(o, params, ctx, { full_key, arr });
614
- }
615
- };
616
-
617
- Eventer.prototype._execSingleTask = async function (o, params, ctx, options) {
618
- const { full_key, arr } = options;
619
-
620
- // 创建任务
621
- let task = this._createTask(o, full_key);
622
-
623
- try {
624
- // 执行事件处理函数
625
- let result = await o.func.apply(o, params);
626
-
627
- // 处理成功结果
628
- this._handleSuccessResult({ result, o, ctx, arr, task });
629
- } catch (e) {
630
- // 处理错误
631
- this._handleSeqTaskError(e, o, ctx, task);
632
- }
633
- };
634
-
635
- Eventer.prototype._createTask = function (o, full_key) {
636
- let task_id = `${o.name}_${Date.now()}`;
637
- let cancelled = false;
638
- const task = {
639
- id: task_id,
640
- cancel: () => { cancelled = true; }
641
- };
642
-
643
- // 添加到进行中的任务列表
644
- let tasks = this._tasks.get(full_key);
645
- tasks.push(task);
646
-
647
- return { task, tasks, cancelled };
648
- };
649
-
650
- Eventer.prototype._handleSuccessResult = function (config) {
651
- const { result, o, ctx, arr, task } = config;
652
-
653
- // 如果任务已取消,则不添加结果
654
- if (!task.cancelled && !ctx.cancelled) {
655
- ctx.results.push(result);
656
-
657
- // 处理执行次数限制
658
- if (o.times >= 0) {
659
- o.times--;
660
- if (o.times <= 0) {
661
- arr.push(o.name);
662
- }
663
- }
664
- }
665
-
666
- // 从进行中的任务列表中移除
667
- task.tasks.splice(task.tasks.indexOf(task.task), 1);
668
- };
669
-
670
- Eventer.prototype._handleSeqTaskError = function (e, o, ctx, task) {
671
- ctx.error_count++;
672
- this.log('error', `事件执行失败 [${ctx.space}:${ctx.event}] - ${o.name}`, e);
673
-
674
- const error_result = {
675
- _error: true,
676
- error: e,
677
- handler: o.name,
678
- timestamp: Date.now()
679
- };
680
-
681
- ctx.results.push(error_result);
682
-
683
- // 全局错误处理器
684
- if (this.config.error_handler && typeof this.config.error_handler === 'function') {
685
- this.config.error_handler(e, { type: 'handler', handler: o.name, ctx });
686
- }
687
-
688
- // 从进行中的任务列表中移除
689
- task.tasks.splice(task.tasks.indexOf(task.task), 1);
690
- };
691
-
692
- /**
693
- * 并行执行事件处理函数
694
- * @param {object} config 配置参数
695
- * @private
696
- */
697
- Eventer.prototype._executeParallel = async function (config) {
698
- const { list, params, ctx, full_key, arr } = config;
699
- let concurrency = this._getConcurrency(params);
700
- // eslint-disable-next-line mm_eslint/class-instance-name
701
- const proc_results = new Array(list.length);
702
-
703
- if (concurrency < Infinity) {
704
- await this._executeBatches({
705
- list, params, ctx, full_key, arr, concurrency, proc_results
706
- });
707
- } else {
708
- await this._executeAllParallel({ list, params, ctx, full_key, arr, proc_results });
709
- }
710
-
711
- this._setResults(ctx, proc_results);
712
- };
713
-
714
- Eventer.prototype._getConcurrency = function (params) {
715
- return params.options && typeof params.options.concurrency === 'number' ?
716
- params.options.concurrency : Infinity;
717
- };
718
-
719
- Eventer.prototype._executeBatches = async function (config) {
720
- const { list, params, ctx, full_key, arr, concurrency, proc_results } = config;
721
-
722
- for (let i = 0; i < list.length && !ctx.cancelled; i += concurrency) {
723
- let batch = list.slice(i, i + concurrency);
724
- let batch_promises = batch.map((obj, batch_idx) => {
725
- let global = i + batch_idx;
726
- return this._executeSingleTask({
727
- obj, params, ctx, full_key, arr, idx: global, proc_results
728
- });
729
- });
730
-
731
- await Promise.allSettled(batch_promises);
732
- }
733
- };
734
-
735
- Eventer.prototype._executeAllParallel = async function (config) {
736
- const { list, params, ctx, full_key, arr, proc_results } = config;
737
-
738
- let promises = list.map((obj, idx) => {
739
- return this._executeSingleTask({ obj, params, ctx, full_key, arr, idx, proc_results });
740
- });
741
-
742
- await Promise.allSettled(promises);
743
- };
744
-
745
- Eventer.prototype._setResults = function (ctx, proc_results) {
746
- ctx.results = proc_results.filter(result => result !== undefined);
747
- };
748
-
749
- /**
750
- * 瀑布流执行事件处理函数
751
- * @param {object} config 配置参数
752
- * @private
753
- */
754
- Eventer.prototype._executeWaterfall = async function (config) {
755
- const { list, params, ctx, full_key, arr, initial_value } = config;
756
- let wate_value = this._getInitialValue(params, initial_value);
757
-
758
- for (let i = 0; i < list.length && !ctx.cancelled; i++) {
759
- let obj = list[i];
760
- ctx.executed++;
761
- obj.last_executed = Date.now();
762
-
763
- let task = this._createWaterfallTask(obj, full_key);
764
- wate_value = await this._execWaterfallStep({
765
- obj, params, ctx, arr, task, wate_value
766
- });
767
- }
768
- };
769
-
770
- Eventer.prototype._getInitialValue = function (params, initial_value) {
771
- return initial_value !== undefined ? initial_value : (params.length > 0 ? params[0] : undefined);
772
- };
773
-
774
- Eventer.prototype._createWaterfallTask = function (obj, full_key) {
775
- let task_id = `${obj.name}_${Date.now()}`;
776
- let cancelled = false;
777
- const task = {
778
- id: task_id,
779
- cancel: () => { cancelled = true; }
780
- };
781
-
782
- let tasks = this._tasks.get(full_key);
783
- tasks.push(task);
784
-
785
- return { task, tasks, cancelled };
786
- };
787
-
788
- Eventer.prototype._execWaterfallStep = async function (config) {
789
- const { obj, params, ctx, arr, task, wate_value } = config;
790
- try {
791
- let result = await obj.func.apply(obj, [wate_value, ...params.slice(1)]);
792
- this._handleWfSuccess({ result, obj, ctx, arr, task });
793
- return result;
794
- } catch (e) {
795
- this._handleWfError({ e, obj, ctx, task });
796
- return wate_value;
797
- }
798
- };
799
-
800
- Eventer.prototype._handleWfSuccess = function (config) {
801
- const { result, obj, ctx, arr, task } = config;
802
- if (!task.cancelled && !ctx.cancelled) {
803
- ctx.results.push(result);
804
- this._handleTimesLimit(obj, arr);
805
- }
806
- this._removeTask(task);
807
- };
808
-
809
- Eventer.prototype._handleWfError = function (config) {
810
- const { e, obj, ctx, task } = config;
811
- ctx.error_count++;
812
- this.log('error', `事件执行失败 [${ctx.space}:${ctx.event}] - ${obj.name}`, e);
813
-
814
- const error_result = {
815
- _error: true,
816
- error: e,
817
- handler: obj.name,
818
- timestamp: Date.now()
819
- };
820
-
821
- ctx.results.push(error_result);
822
- this._callErrorHandler(e, obj, ctx);
823
- this._removeTask(task);
824
- };
825
-
826
- Eventer.prototype._handleTimesLimit = function (obj, arr) {
827
- if (obj.times >= 0) {
828
- obj.times--;
829
- if (obj.times <= 0) {
830
- arr.push(obj.name);
831
- }
832
- }
833
- };
834
-
835
- Eventer.prototype._removeTask = function (task) {
836
- task.tasks.splice(task.tasks.indexOf(task.task), 1);
837
- };
838
-
839
- Eventer.prototype._callErrorHandler = function (e, obj, ctx) {
840
- if (this.config.error_handler && typeof this.config.error_handler === 'function') {
841
- this.config.error_handler(e, { type: 'handler', handler: obj.name, ctx });
842
- }
843
- };
844
-
845
- /**
846
- * 竞争执行模式 - 返回第一个完成的结果
847
- * @param {object} config 配置参数
848
- * @param {Array} config.list 事件列表
849
- * @param {Array} config.params 参数
850
- * @param {object} config.ctx 上下文
851
- * @param {string} config.strategy 执行策略
852
- * @returns {Promise<object>} 返回包含results和cancel方法的对象
853
- * @private
854
- */
855
- Eventer.prototype._executeRace = async function (config) {
856
- const { list, params, ctx, full_key, arr } = config;
857
- let promises = this._createRacePromises({ list, params, ctx, full_key, arr });
858
-
859
- return await this._runRace(promises);
860
- };
861
-
862
- Eventer.prototype._createRacePromises = function (config) {
863
- const { list, params, ctx, full_key, arr } = config;
864
- const promises = [];
865
-
866
- for (let i = 0; i < list.length && !ctx.cancelled; i++) {
867
- let obj = list[i];
868
- ctx.executed++;
869
- obj.last_executed = Date.now();
870
-
871
- let promise = this._createRacePromise({ obj, params, ctx, full_key, arr });
872
- promises.push(promise);
873
- }
874
-
875
- return promises;
876
- };
877
-
878
- Eventer.prototype._createRacePromise = function (config) {
879
- const { obj, params, ctx, full_key, arr } = config;
880
- let task = this._createRaceTask(obj, full_key);
881
-
882
- return (async () => {
883
- try {
884
- let result = await obj.func.apply(obj, params);
885
- return this._handleRaceSuccess({ result, obj, ctx, arr, task });
886
- } catch (e) {
887
- return this._handleRaceError(e, obj, ctx, task);
888
- } finally {
889
- this._removeTask(task);
890
- }
891
- })();
892
- };
893
-
894
- Eventer.prototype._createRaceTask = function (obj, full_key) {
895
- let task_id = `${obj.name}_${Date.now()}`;
896
- let cancelled = false;
897
- const task = {
898
- id: task_id,
899
- cancel: () => { cancelled = true; }
900
- };
901
-
902
- let tasks = this._tasks.get(full_key);
903
- tasks.push(task);
904
-
905
- return { task, tasks, cancelled };
906
- };
907
-
908
- Eventer.prototype._handleRaceSuccess = function (config) {
909
- const { result, obj, ctx, arr, task } = config;
910
-
911
- if (!task.cancelled && !ctx.cancelled) {
912
- ctx.results.push(result);
913
- this._handleTimesLimit(obj, arr);
914
- return { success: true, result, handler: obj.name };
915
- }
916
- return { success: false, cancelled: true };
917
- };
918
-
919
- Eventer.prototype._handleRaceError = function (e, obj, ctx, task) {
920
- ctx.error_count++;
921
- this.log('error', `事件执行失败 [${ctx.space}:${ctx.event}] - ${obj.name}`, e);
922
-
923
- const error_result = {
924
- _error: true,
925
- error: e,
926
- handler: obj.name,
927
- timestamp: Date.now()
928
- };
929
-
930
- ctx.results.push(error_result);
931
- this._callErrorHandler(e, obj, ctx);
932
-
933
- return { success: false, error: e, handler: obj.name };
934
- };
935
-
936
- Eventer.prototype._runRace = async function (promises) {
937
- if (promises.length > 0) {
938
- let race = await Promise.race(promises);
939
- return race;
940
- }
941
- return null;
942
- };
943
-
944
- /**
945
- * 执行单个任务(并行执行时使用)
946
- * @param {object} config 配置参数
947
- * @private
948
- */
949
- Eventer.prototype._executeSingleTask = async function (config) {
950
- const { obj, params, ctx, full_key, arr, idx, proc_results } = config;
951
- obj.last_executed = Date.now();
952
-
953
- // 创建任务
954
- let task_info = this._createParallelTask(obj, full_key);
955
-
956
- try {
957
- let result = await obj.func.apply(obj, params);
958
- this._handleTaskSuccess({ result, obj, ctx, arr, idx, proc_results, task_info });
959
- } catch (err) {
960
- this._handleTaskError({ err, obj, ctx, idx, proc_results, task_info });
961
- }
962
- };
963
-
964
- Eventer.prototype._createParallelTask = function (obj, full_key) {
965
- let task_id = `${obj.name}_${Date.now()}`;
966
- let cancelled = false;
967
- const task = {
968
- id: task_id,
969
- cancel: () => { cancelled = true; }
970
- };
971
-
972
- // 添加到进行中的任务列表
973
- let tasks = this._tasks.get(full_key);
974
- tasks.push(task);
975
-
976
- return { task, tasks, cancelled };
977
- };
978
-
979
- Eventer.prototype._handleTaskSuccess = function (config) {
980
- const { result, obj, ctx, arr, idx, proc_results, task_info } = config;
981
-
982
- // 从进行中的任务列表中移除
983
- task_info.tasks.splice(task_info.tasks.indexOf(task_info.task), 1);
984
-
985
- if (!task_info.cancelled && !ctx.cancelled) {
986
- proc_results[idx] = result;
987
-
988
- // 处理执行次数限制
989
- if (obj.times >= 0) {
990
- obj.times--;
991
- if (obj.times <= 0) {
992
- arr.push(obj.name);
993
- }
994
- }
995
- }
996
- };
997
-
998
- Eventer.prototype._handleTaskError = function (config) {
999
- const { err, obj, ctx, idx, proc_results, task_info } = config;
1000
-
1001
- // 从进行中的任务列表中移除
1002
- task_info.tasks.splice(task_info.tasks.indexOf(task_info.task), 1);
1003
-
1004
- if (!task_info.cancelled && !ctx.cancelled) {
1005
- const error_result = {
1006
- _error: true,
1007
- error: err,
1008
- handler: obj.name,
1009
- timestamp: Date.now()
1010
- };
1011
- proc_results[idx] = error_result;
1012
-
1013
- // 全局错误处理器
1014
- if (this.config.error_handler && typeof this.config.error_handler === 'function') {
1015
- this.config.error_handler(err, { type: 'handler', handler: obj.name, ctx });
1016
- }
1017
- }
1018
- };
1019
-
1020
- /**
1021
- * 执行事件(支持中间件和命名空间)
1022
- * @param {string} key 事件关键字,支持space:key格式
1023
- * @param {object} params 传递参数
1024
- * @returns {Promise<object>} 返回包含results和cancel方法的对象
1025
- */
1026
- Eventer.prototype.run = async function (key, ...params) {
1027
- return this._execute(key, { exec_mode: 'sequential' }, ...params);
1028
- };
1029
-
1030
- /**
1031
- * 触发事件
1032
- * @param {string} key 事件关键,支持space:key格式
1033
- * @param {object} params 传递参数
1034
- * @returns {Promise<object>} 返回包含results和cancel方法的对象
1035
- */
1036
- Eventer.prototype.emit = function (key, ...params) {
1037
- // 内部调用 _execute 方法,但不等待结果
1038
- try {
1039
- let result = this._execute(key, { exec_mode: 'sequential' }, ...params);
1040
- result.catch(e => this.log('error', '事件异步执行失败:', e));
1041
- return {
1042
- ...result,
1043
- cancel: () => {
1044
- try {
1045
- return result.then(r => r && typeof r.cancel === 'function' && r.cancel());
1046
- } catch (cancel_error) {
1047
- this.log('error', `事件取消失败 [${key}]`, cancel_error);
1048
- return Promise.resolve();
1049
- }
1050
- }
1051
- };
1052
- } catch (error) {
1053
- this.log('error', `事件触发失败 [${key}]`, error);
1054
- // 返回一个安全的默认结果
1055
- return {
1056
- results: [],
1057
- cancelled: false,
1058
- cancel: () => { },
1059
- error: error
1060
- };
1061
- }
1062
- };
1063
-
1064
- /**
1065
- * 异步触发事件,按顺序执行等待完成
1066
- * @param {string} key 事件关键字,支持space:key格式
1067
- * @param {...any} args 事件参数
1068
- * @returns {Promise} - 事件触发结果
1069
- */
1070
- Eventer.prototype.emitWait = async function (key, ...args) {
1071
- try {
1072
- let result = await this._execute(key, { exec_mode: 'sequential' }, ...args);
1073
- return result.results || [];
1074
- } catch (error) {
1075
- this.log('error', `等待事件触发失败 [${key}]`, error);
1076
- return [];
1077
- }
1078
- };
1079
-
1080
- /**
1081
- * 异步触发事件,并发执行不等待
1082
- * @param {string} key 事件关键字,支持space:key格式
1083
- * @param {...any} args 事件参数
1084
- * @returns {boolean} - 是否有监听者
1085
- */
1086
- Eventer.prototype.emitAsync = async function (key, ...args) {
1087
- try {
1088
- return this._execAsync(key, args);
1089
- } catch (global_error) {
1090
- this.log('error', `异步事件触发失败 [${key}]`, global_error);
1091
- return false;
1092
- }
1093
- };
1094
-
1095
- Eventer.prototype._execAsync = function (key, args) {
1096
- // 解析命名空间
1097
- let parsed = this._parseKey(key);
1098
- let space = parsed.space;
1099
- let event_key = parsed.key;
1100
- let full_key = `${space}:${event_key}`;
1101
-
1102
- // 获取事件列表
1103
- let list = this._dict[space] && this._dict[space][event_key];
1104
-
1105
- if (!list || list.length === 0) {
1106
- return false;
1107
- }
1108
-
1109
- // 立即启动所有监听器,但不等待
1110
- list.forEach(handler => {
1111
- this._executeAsyncHandler(handler, args, full_key);
1112
- });
1113
-
1114
- return true;
1115
- };
1116
-
1117
- Eventer.prototype._executeAsyncHandler = function (handler, args, full_key) {
1118
- try {
1119
- // 使用 Promise.resolve 确保异步执行
1120
- Promise.resolve(handler.func(...args))
1121
- .catch(error => {
1122
- this._handleAsyncError(error, full_key, args);
1123
- });
1124
- } catch (sync_error) {
1125
- this._handleSyncError(sync_error, full_key, args);
1126
- }
1127
- };
1128
-
1129
- Eventer.prototype._handleAsyncError = function (error, full_key, args) {
1130
- // 错误处理 - 记录但不抛出
1131
- this.log('error', `异步监听器错误 [${full_key}]:`, error);
1132
- try {
1133
- this.emit('async:error', error, full_key, args);
1134
- } catch (error) {
1135
- this.log('error', '错误事件触发失败 [async:error]', error);
1136
- }
1137
- };
1138
-
1139
- Eventer.prototype._handleSyncError = function (sync_error, full_key, args) {
1140
- // 同步错误处理
1141
- this.log('error', `同步监听器错误 [${full_key}]:`, sync_error);
1142
- try {
1143
- this.emit('sync:error', sync_error, full_key, args);
1144
- } catch (error) {
1145
- this.log('error', '错误事件触发失败 [sync:error]', error);
1146
- }
1147
- };
1148
-
1149
- /**
1150
- * 异步触发事件,并发执行等待完成
1151
- * @param {string} key 事件关键字,支持space:key格式
1152
- * @param {...any} args 事件参数
1153
- * @returns {Promise<Array>} - 所有监听器的执行结果
1154
- */
1155
- Eventer.prototype.emitAll = async function (key, ...args) {
1156
- try {
1157
- let result = await this._execute(key, { exec_mode: 'parallel' }, ...args);
1158
- return result.results || [];
1159
- } catch (error) {
1160
- this.log('error', `并发事件触发失败 [${key}]`, error);
1161
- return [];
1162
- }
1163
- };
1164
-
1165
- /**
1166
- * 异步触发事件,竞争执行
1167
- * @param {string} key 事件关键字,支持space:key格式
1168
- * @param {...any} args 事件参数
1169
- * @returns {Promise} - 第一个完成的结果
1170
- */
1171
- Eventer.prototype.emitRace = async function (key, ...args) {
1172
- try {
1173
- let result = await this._execute(key, { exec_mode: 'race' }, ...args);
1174
- return result.race || null;
1175
- } catch (error) {
1176
- this.log('error', `竞争事件触发失败 [${key}]`, error);
1177
- return null;
1178
- }
1179
- };
1180
-
1181
- /**
1182
- * 异步触发事件,返回第一个有返回值的结果(不阻塞其他监听器)
1183
- * @param {string} key 事件关键字,支持space:key格式
1184
- * @param {...any} args 事件参数
1185
- * @returns {Promise} - 第一个有返回值(非 undefined)的监听器结果
1186
- * 所有监听器并行执行,返回第一个有返回值(非 undefined)的结果,返回 undefined 的监听器被跳过,其他监听器继续在后台执行不受影响
1187
- */
1188
- Eventer.prototype.emitFirst = async function (key, ...args) {
1189
- try {
1190
- let parsed = this._parseKey(key);
1191
- let space = parsed.space;
1192
- let event_key = parsed.key;
1193
-
1194
- let list = this._dict[space] && this._dict[space][event_key];
1195
- if (!list || list.length === 0) {
1196
- return undefined;
1197
- }
1198
-
1199
- return await new Promise(resolve => {
1200
- let settled = false;
1201
- let pending = list.length;
1202
-
1203
- for (let handler of list) {
1204
- Promise.resolve(handler.func(...args)).then(result => {
1205
- if (!settled && result !== undefined) {
1206
- settled = true;
1207
- resolve(result);
1208
- }
1209
- pending--;
1210
- if (pending === 0 && !settled) {
1211
- resolve(undefined);
1212
- }
1213
- }).catch(() => {
1214
- pending--;
1215
- if (pending === 0 && !settled) {
1216
- resolve(undefined);
1217
- }
1218
- });
1219
- }
1220
- });
1221
- } catch (error) {
1222
- this.log('error', `首个结果事件触发失败 [${key}]`, error);
1223
- return undefined;
1224
- }
1225
- };
1226
-
1227
- /**
1228
- * 异步触发事件,瀑布流执行
1229
- * @param {string} key 事件关键字,支持space:key格式
1230
- * @param {*} value 初始值
1231
- * @param {...any} args 事件参数
1232
- * @returns {Promise} - 最后一个事件监听者的结果
1233
- */
1234
- Eventer.prototype.emitWaterfall = async function (key, value, ...args) {
1235
- try {
1236
- let result = await this._execute(key, {
1237
- exec_mode: 'waterfall',
1238
- initial_value: value
1239
- }, ...args);
1240
- return result.waterfall || value;
1241
- } catch (error) {
1242
- this.log('error', `瀑布流事件触发失败 [${key}]`, error);
1243
- return value;
1244
- }
1245
- };
1246
-
1247
- /**
1248
- * 确保命名空间在映射中
1249
- * @private
1250
- * @param {string} name 命名空间名称
1251
- */
1252
- Eventer.prototype._ensureNs = function (name) {
1253
- if (!this._space[name]) {
1254
- this._space[name] = true;
1255
- }
1256
- };
1257
-
1258
- /**
1259
- * 执行单个命名空间的事件处理函数
1260
- * @private
1261
- * @param {string} name 命名空间名称
1262
- * @param {string} key 事件关键字
1263
- * @param {Array} params 事件参数
1264
- * @returns {object} 包含结果和需要移除的事件名称的对象
1265
- */
1266
- Eventer.prototype._execNsEvents = async function (name, key, params) {
1267
- let list = this._dict[name][key];
1268
- const name_results = [];
1269
- const arr = []; // 存储需要移除的事件
1270
-
1271
- // 执行事件处理函数
1272
- for (let i = 0; i < list.length; i++) {
1273
- try {
1274
- let obj = list[i];
1275
- // 执行事件处理函数
1276
- let result = await obj.func.apply(obj, params);
1277
- name_results.push(result);
1278
-
1279
- // 处理执行次数限制
1280
- if (obj.times >= 0) {
1281
- obj.times--;
1282
- if (obj.times <= 0) {
1283
- arr.push(obj.name);
1284
- }
1285
- }
1286
- } catch (e) {
1287
- // 记录错误但不中断执行
1288
- this.log('error', `事件执行失败 [${name}:${key}] - ${list[i].name}`, e);
1289
- name_results.push({
1290
- _error: true,
1291
- error: e,
1292
- handler: list[i].name
1293
- });
1294
- }
1295
- }
1296
-
1297
- return { name_results, arr };
1298
- };
1299
-
1300
- /**
1301
- * 移除已执行完的事件
1302
- * @private
1303
- * @param {string} name 命名空间名称
1304
- * @param {string} key 事件关键字
1305
- * @param {Array} arr 需要移除的事件名称数组
1306
- */
1307
- Eventer.prototype._removeEvents = function (name, key, arr) {
1308
- for (let i = 0; i < arr.length; i++) {
1309
- this.del(`${name}:${key}`, arr[i]);
1310
- }
1311
- };
1312
-
1313
- Eventer.prototype.emitAllNamespaces = async function (key, ...params) {
1314
- const results = {};
1315
- // 确保遍历所有命名空间,包括动态创建的
1316
- for (let name in this._dict) {
1317
- // 确保命名空间在space映射中
1318
- this._ensureNs(name);
1319
-
1320
- // 检查该命名空间下是否存在该事件
1321
- if (this._dict[name] && this._dict[name][key]) {
1322
- const { name_results, arr } = await this._execNsEvents(name, key, params);
1323
-
1324
- // 移除已执行完的事件
1325
- this._removeEvents(name, key, arr);
1326
-
1327
- results[name] = name_results;
1328
- }
1329
- }
1330
- return results;
1331
- };
1332
-
1333
- /**
1334
- * 删除单个事件监听器
1335
- * @private
1336
- * @param {Array} events 事件列表
1337
- * @param {string | number} index_or_name 事件索引或名称
1338
- * @returns {boolean} 删除成功返回true,否则返回false
1339
- */
1340
- Eventer.prototype._removeSingleEvent = function (events, index_or_name) {
1341
- if (typeof (index_or_name) === 'number') {
1342
- // 按索引删除
1343
- if (index_or_name >= 0 && index_or_name < events.length) {
1344
- events.splice(index_or_name, 1);
1345
- return true;
1346
- }
1347
- } else {
1348
- // 根据名称删除事件
1349
- for (let j = events.length - 1; j >= 0; j--) {
1350
- if (events[j].name === index_or_name) {
1351
- events.splice(j, 1);
1352
- return true;
1353
- }
1354
- }
1355
- }
1356
- return false;
1357
- };
1358
-
1359
- /**
1360
- * 删除整个事件
1361
- * @private
1362
- * @param {string} space 命名空间
1363
- * @param {string} event_key 事件键
1364
- * @param {string} full_key 完整事件关键字
1365
- * @returns {boolean} 删除成功返回true
1366
- */
1367
- Eventer.prototype._removeEntireEvent = function (space, event_key, full_key) {
1368
- // 安全检查:确保命名空间和事件存在
1369
- if (!this._dict[space] || !this._dict[space][event_key]) {
1370
- return false;
1371
- }
1372
-
1373
- // 删除整个事件
1374
- delete this._dict[space][event_key];
1375
-
1376
- // 清理相关的事件链
1377
- if (this._chain) {
1378
- for (let chain_key in this._chain) {
1379
- if (chain_key === full_key) {
1380
- delete this._chain[chain_key];
1381
- } else if (this._chain[chain_key] && Array.is_array(this._chain[chain_key]) &&
1382
- this._chain[chain_key].includes(full_key)) {
1383
- delete this._chain[chain_key];
1384
- }
1385
- }
1386
- }
1387
-
1388
- return true;
1389
- };
1390
-
1391
- /**
1392
- * 自动清理空的事件列表和命名空间
1393
- * @private
1394
- * @param {string} space 命名空间
1395
- * @param {string} key 事件关键字
1396
- * @param {Array} events 事件列表
1397
- * @param {string | number} index_or_name 事件索引或名称
1398
- */
1399
- Eventer.prototype._autoCleanEvents = function (space, key, events, index_or_name) {
1400
- if (!this.config.auto_clean) return;
1401
-
1402
- // 安全检查:确保命名空间存在
1403
- if (!this._dict[space]) {
1404
- return;
1405
- }
1406
-
1407
- // 清理空的事件列表
1408
- if (index_or_name && events && events.length === 0) {
1409
- // 安全检查:确保事件键存在
1410
- if (this._dict[space][key]) {
1411
- delete this._dict[space][key];
1412
- }
1413
- }
1414
-
1415
- // 如果命名空间为空,则删除命名空间
1416
- if (this._dict[space] && Object.keys(this._dict[space]).length === 0) {
1417
- delete this._dict[space];
1418
- if (this._space && this._space[space]) {
1419
- delete this._space[space];
1420
- }
1421
- }
1422
- };
1423
-
1424
- /**
1425
- * 删除事件
1426
- * @param {string} key 事件关键字,支持space:key格式
1427
- * @param {number | string} index_or_name 事件集索引或名称
1428
- * @returns {boolean} 删除成功返回true,否则返回false
1429
- */
1430
- Eventer.prototype.off = function (key, index_or_name) {
1431
- // 入参校验
1432
- if (!key || typeof key !== 'string') {
1433
- throw new Error('事件关键字必须是非空字符串');
1434
- }
1435
-
1436
- // 解析命名空间
1437
- let parsed = this._parseKey(key);
1438
- let space = parsed.space;
1439
- let event_key = parsed.key;
1440
- let full_key = `${space}:${event_key}`;
1441
-
1442
- // 检查事件是否存在
1443
- if (!this._dict[space] || !this._dict[space][event_key]) {
1444
- return false;
1445
- }
1446
-
1447
- let events = this._dict[space][event_key];
1448
- let removed = false;
1449
-
1450
- if (index_or_name) {
1451
- // 删除单个事件
1452
- removed = this._removeSingleEvent(events, index_or_name);
1453
- } else {
1454
- // 删除整个事件
1455
- removed = this._removeEntireEvent(space, event_key, full_key);
1456
- }
1457
-
1458
- // 自动清理
1459
- if (removed) {
1460
- this._autoCleanEvents(space, event_key, events, index_or_name);
1461
- }
1462
-
1463
- return removed;
1464
- };
1465
-
1466
- Eventer.prototype.add = Eventer.prototype.on;
1467
- Eventer.prototype.del = Eventer.prototype.off;
1468
-
1469
- /**
1470
- * 删除命名空间中的所有事件
1471
- * @param {string} name 命名空间
1472
- * @returns {boolean} 删除成功返回true,否则返回false
1473
- */
1474
- Eventer.prototype.clearNamespace = function (name) {
1475
- if (!name || !this._dict[name]) {
1476
- return false;
1477
- }
1478
- delete this._dict[name];
1479
- delete this._space[name];
1480
- return true;
1481
- };
1482
-
1483
- /**
1484
- * 获取事件列表
1485
- * @param {string} key 事件关键字,如果为空则获取所有事件,支持space:key格式
1486
- * @returns {Array | object} 返回事件列表或所有事件对象
1487
- */
1488
- Eventer.prototype.getEvents = function (key) {
1489
- if (key) {
1490
- // 解析命名空间
1491
- const { space, key: event_key } = this._parseKey(key);
1492
- return this._dict[space] &&
1493
-
1494
- this._dict[space][event_key] ? [...this._dict[space][event_key]] : [];
1495
- }
1496
- // 返回深拷贝的所有事件
1497
- const result = {};
1498
- for (let name in this._dict) {
1499
- result[name] = {};
1500
- for (let key in this._dict[name]) {
1501
- result[name][key] = [...this._dict[name][key]];
1502
- }
1503
- }
1504
- return result;
1505
- };
1506
-
1507
- /**
1508
- * 获取所有命名空间
1509
- * @returns {Array} 返回所有命名空间数组
1510
- */
1511
- Eventer.prototype.getNamespace = function () {
1512
- return Object.keys(this._space);
1513
- };
1514
-
1515
- /**
1516
- * 清空所有事件和资源
1517
- * @param {boolean} keep_space 是否保留命名空间定义,默认false
1518
- * @returns {Eventer} 返回当前实例,支持链式调用
1519
- */
1520
- Eventer.prototype.clear = function (keep_space = false) {
1521
- // 取消所有进行中的任务
1522
- if (this._tasks) {
1523
- this._tasks.forEach((tasks, key) => {
1524
- tasks.forEach(task => {
1525
- if (task && typeof task.cancel === 'function') {
1526
- task.cancel();
1527
- }
1528
- });
1529
- });
1530
- this._tasks.clear();
1531
- }
1532
-
1533
- // 清空事件字典
1534
- this._dict = {};
1535
-
1536
- // 清空事件链
1537
- this._chain = {};
1538
-
1539
- // 清空暂停状态
1540
- if (this._paused) {
1541
- this._paused.clear();
1542
- }
1543
- if (this._paused_space) {
1544
- this._paused_space.clear();
1545
- }
1546
- this._paused_global = false;
1547
-
1548
- // 保留命名空间定义
1549
- if (!keep_space) {
1550
- this._space = {};
1551
- // 重新初始化默认命名空间
1552
- this._space[this.config.default_name] = true;
1553
- }
1554
-
1555
- return this;
1556
- };
1557
-
1558
- /**
1559
- * 检查事件是否存在
1560
- * @param {string} key 事件关键字,支持space:key格式
1561
- * @param {string} name 事件名称(可选)
1562
- * @returns {boolean} 事件存在返回true,否则返回false
1563
- */
1564
- Eventer.prototype.has = function (key, name) {
1565
- // 解析命名空间
1566
- let parsed = this._parseKey(key);
1567
- let space = parsed.space;
1568
- let event_key = parsed.key;
1569
-
1570
- if (!this._dict[space] || !this._dict[space][event_key]) {
1571
- return false;
1572
- }
1573
-
1574
- if (name) {
1575
- let list = this._dict[space][event_key];
1576
- for (let i = 0; i < list.length; i++) {
1577
- if (list[i].name === name) {
1578
- return true;
1579
- }
1580
- }
1581
- return false;
1582
- }
1583
-
1584
- return true;
1585
- };
1586
-
1587
- /**
1588
- * 获取事件数量
1589
- * @param {string} key 事件关键字,如果为空则获取所有事件数量,支持space:key格式或space:*格式
1590
- * @returns {number} 返回事件数量
1591
- */
1592
- Eventer.prototype.count = function (key) {
1593
- if (key) {
1594
- // 解析可能的命名空间模式
1595
- if (key.endsWith(':*')) {
1596
- // 统计命名空间下所有事件
1597
- let space = key.split(':')[0];
1598
- if (this._dict[space]) {
1599
- let total = 0;
1600
- for (let key in this._dict[space]) {
1601
- total += this._dict[space][key].length;
1602
- }
1603
- return total;
1604
- }
1605
- return 0;
1606
- }
1607
-
1608
- // 解析具体事件
1609
- const { space, key: event_key } = this._parseKey(key);
1610
- return this._dict[space] &&
1611
-
1612
- this._dict[space][event_key] ? this._dict[space][event_key].length : 0;
1613
- }
1614
-
1615
- // 统计所有事件
1616
- let total = 0;
1617
- for (let name in this._dict) {
1618
- for (let key in this._dict[name]) {
1619
- total += this._dict[name][key].length;
1620
- }
1621
- }
1622
- return total;
1623
- };
1624
-
1625
- /**
1626
- * 添加事件中间件
1627
- * @param {string} type 中间件类型,'before' 或 'after'
1628
- * @param {Function} middleware 中间件函数,接收ctx参数
1629
- * @returns {Eventer} 返回当前实例,支持链式调用
1630
- */
1631
- Eventer.prototype.use = function (type, middleware) {
1632
- if (type !== 'before' && type !== 'after') {
1633
- throw new Error('中间件类型必须是 "before" 或 "after"');
1634
- }
1635
- if (typeof middleware !== 'function') {
1636
- throw new Error('中间件必须是一个函数');
1637
- }
1638
-
1639
- if (!this._middleware[type]) {
1640
- this._middleware[type] = [];
1641
- }
1642
- this._middleware[type].push(middleware);
1643
- return this;
1644
- };
1645
-
1646
- /**
1647
- * 添加事件链式触发关系
1648
- * @param {string} from_event 源事件,支持space:key格式
1649
- * @param {string | Array} to_events 目标事件,可以是单个事件或事件数组
1650
- * @returns {Eventer} 返回当前实例,支持链式调用
1651
- */
1652
- Eventer.prototype.chain = function (from_event, to_events) {
1653
- // 入参校验
1654
- this._validateChainInput(from_event, to_events);
1655
-
1656
- // 解析源事件
1657
- let full_from_event = this._getFullEventKey(from_event);
1658
-
1659
- // 初始化事件链
1660
- this._initEventChain(full_from_event);
1661
-
1662
- // 添加目标事件
1663
- this._addTargetEvents(full_from_event, to_events);
1664
-
1665
- return this;
1666
- };
1667
-
1668
- Eventer.prototype._validateChainInput = function (from_event, to_events) {
1669
- if (!from_event || typeof from_event !== 'string') {
1670
- throw new Error('源事件必须是非空字符串');
1671
- }
1672
- };
1673
-
1674
- Eventer.prototype._getFullEventKey = function (event) {
1675
- const { space, key } = this._parseKey(event);
1676
- return `${space}:${key}`;
1677
- };
1678
-
1679
- Eventer.prototype._initEventChain = function (full_from_event) {
1680
- if (!this._chain[full_from_event]) {
1681
- this._chain[full_from_event] = [];
1682
- }
1683
- };
1684
-
1685
- Eventer.prototype._addTargetEvents = function (full_from_event, to_events) {
1686
- // 确保目标事件是数组
1687
- let target_events = Array.isArray(to_events) ? to_events : [to_events];
1688
-
1689
- for (let i = 0; i < target_events.length; i++) {
1690
- this._addTargetEvent(full_from_event, target_events[i]);
1691
- }
1692
- };
1693
-
1694
- Eventer.prototype._addTargetEvent = function (full_from_event, to_event) {
1695
- if (typeof to_event !== 'string') {
1696
- throw new Error('目标事件必须是非空字符串');
1697
- }
1698
-
1699
- // 解析目标事件
1700
- let full_to_event = this._getFullEventKey(to_event);
1701
-
1702
- // 避免重复添加
1703
- if (!this._chain[full_from_event].includes(full_to_event)) {
1704
- this._chain[full_from_event].push(full_to_event);
1705
- }
1706
- };
1707
-
1708
- /**
1709
- * 移除事件链式触发关系
1710
- * @param {string} from_event 源事件,支持space:key格式
1711
- * @param {string | Array} to_events 目标事件,可以是单个事件或事件数组(可选,不提供则移除所有关联)
1712
- * @returns {Eventer} 返回当前实例,支持链式调用
1713
- */
1714
- Eventer.prototype.unchain = function (from_event, to_events) {
1715
- // 入参校验
1716
- if (!from_event || typeof from_event !== 'string') {
1717
- throw new Error('源事件必须是非空字符串');
1718
- }
1719
-
1720
- // 解析源事件
1721
- const { space: from_space, key: fromkey } = this._parseKey(from_event);
1722
- let full_from_event = `${from_space}:${fromkey}`;
1723
-
1724
- // 如果源事件不存在事件链,直接返回
1725
- if (!this._chain[full_from_event]) {
1726
- return this;
1727
- }
1728
-
1729
- if (to_events) {
1730
- this._removeTargetEvents(full_from_event, to_events);
1731
- } else {
1732
- // 移除整个事件链
1733
- delete this._chain[full_from_event];
1734
- }
1735
-
1736
- return this;
1737
- };
1738
-
1739
- Eventer.prototype._removeTargetEvents = function (full_from_event, to_events) {
1740
- let target_events = Array.isArray(to_events) ? to_events : [to_events];
1741
-
1742
- for (let i = 0; i < target_events.length; i++) {
1743
- this._removeTargetEvent(full_from_event, target_events[i]);
1744
- }
1745
-
1746
- // 如果事件链为空,则删除整个事件链
1747
- if (this._chain[full_from_event].length === 0) {
1748
- delete this._chain[full_from_event];
1749
- }
1750
- };
1751
-
1752
- Eventer.prototype._removeTargetEvent = function (full_from_event, to_event) {
1753
- if (typeof to_event !== 'string') {
1754
- throw new Error('目标事件必须是非空字符串');
1755
- }
1756
-
1757
- // 解析目标事件
1758
- const { space: to_space, key: tokey } = this._parseKey(to_event);
1759
- let full_to_event = `${to_space}:${tokey}`;
1760
-
1761
- // 检查事件链是否存在
1762
- if (!this._chain[full_from_event]) {
1763
- this.log('warn', `事件链不存在: ${full_from_event} -> ${full_to_event}`);
1764
- return;
1765
- }
1766
-
1767
- // 查找并删除事件链
1768
- let index = this._chain[full_from_event].indexOf(full_to_event);
1769
- if (index === -1) {
1770
- this.log('warn', `事件链不存在: ${full_from_event} -> ${full_to_event}`);
1771
- return;
1772
- }
1773
-
1774
- this._chain[full_from_event].splice(index, 1);
1775
- };
1776
-
1777
- /**
1778
- * 获取事件链
1779
- * @param {string} event 事件关键字,支持space:key格式
1780
- * @returns {Array} 返回事件链数组
1781
- */
1782
- Eventer.prototype.getChains = function (event) {
1783
- if (!event) {
1784
- return Object.keys(this._chain);
1785
- }
1786
-
1787
- // 解析事件
1788
- const { space, key } = this._parseKey(event);
1789
- let full_event = `${space}:${key}`;
1790
-
1791
- return this._chain[full_event] ? [...this._chain[full_event]] : [];
1792
- };
1793
-
1794
- /**
1795
- * 触发下一级事件链事件
1796
- * @private
1797
- * @param {string} current_event 当前触发的事件
1798
- * @param {Array} params 传递的参数
1799
- * @returns {Promise<void>}
1800
- */
1801
- Eventer.prototype._triggerChain = async function (current_event, params) {
1802
- if (!this.config.chain_enabled || !this._chain[current_event]) {
1803
- return;
1804
- }
1805
-
1806
- // 循环触发下一级事件
1807
- for (let next_event of this._chain[current_event]) {
1808
- await this._execChainItem(next_event, params);
1809
- }
1810
- };
1811
-
1812
- /**
1813
- * 执行单个链上事件(包含中间件)
1814
- * @private
1815
- * @param {string} key 要执行的事件
1816
- * @param {Array} params 参数
1817
- * @returns {Promise<Array>} 执行结果
1818
- */
1819
- Eventer.prototype._execChainItem = async function (key, params) {
1820
- // 解析命名空间
1821
- const { space, key: innerkey } = this._parseKey(key);
1822
- let list = this._dict[space] && this._dict[space][innerkey];
1823
- const results = [];
1824
-
1825
- // 创建上下文对象
1826
- let ctx = this._createChainContext(space, innerkey, key, params);
1827
-
1828
- // 如果有事件处理函数,执行它们
1829
- if (list && list.length > 0) {
1830
- await this._executeChainItemWithMiddleware(list, ctx, results);
1831
- }
1832
-
1833
- // 递归触发下一级事件
1834
- if (this._chain[key]) {
1835
- await this._triggerChain(key, params);
1836
- }
1837
-
1838
- return results;
1839
- };
1840
-
1841
- Eventer.prototype._createChainContext = function (space, innerkey, key, params) {
1842
- let start_time = Date.now();
1843
- return {
1844
- space,
1845
- event: innerkey,
1846
- full_event: key,
1847
- params,
1848
- results: [],
1849
- start_time: start_time,
1850
- executed: 0,
1851
- error_count: 0
1852
- };
1853
- };
1854
-
1855
- Eventer.prototype._execChainMware = async function (list, ctx, results) {
1856
- // 执行前置中间件
1857
- await this._runChainMiddleware('before', ctx);
1858
-
1859
- // 执行事件处理函数
1860
- await this._executeChainHandlers(list, ctx, results);
1861
-
1862
- // 执行后置中间件
1863
- await this._runChainMiddleware('after', ctx);
1864
- };
1865
-
1866
- Eventer.prototype._runChainMiddleware = async function (type, ctx) {
1867
- try {
1868
- if (type === 'after') {
1869
- ctx.end_time = Date.now();
1870
- ctx.duration = ctx.end_time - ctx.start_time;
1871
- }
1872
- await this._runMiddleware(type, ctx);
1873
- } catch (error) {
1874
- this.log('error', `事件链${type}中间件执行失败 [${ctx.space}:${ctx.event}]`, error);
1875
- }
1876
- };
1877
-
1878
- Eventer.prototype._execChainHandlers = async function (list, ctx, results) {
1879
- for (let i = 0; i < list.length; i++) {
1880
- await this._execChainHandler(list[i], ctx, results);
1881
- }
1882
- };
1883
-
1884
- Eventer.prototype._execChainHandler = async function (obj, ctx, results) {
1885
- try {
1886
- ctx.executed++;
1887
-
1888
- // 执行事件处理函数
1889
- let result = await obj.func.apply(obj, ctx.params);
1890
- results.push(result);
1891
- ctx.results.push(result);
1892
-
1893
- // 处理执行次数限制
1894
- this._handleChainTimes(obj, ctx);
1895
- } catch (e) {
1896
- this._handleChainError(e, obj, ctx, results);
1897
- }
1898
- };
1899
-
1900
- Eventer.prototype._handleChainTimes = function (obj, ctx) {
1901
- if (obj.times >= 0) {
1902
- obj.times--;
1903
- if (obj.times <= 0) {
1904
- this.del(`${ctx.space}:${ctx.event}`, obj.name);
1905
- }
1906
- }
1907
- };
1908
-
1909
- Eventer.prototype._handleChainError = function (e, obj, ctx, results) {
1910
- ctx.error_count++;
1911
- this.log('error', `事件链执行失败 [${ctx.space}:${ctx.event}] - ${obj.name}`, e);
1912
-
1913
- const error_result = {
1914
- _error: true,
1915
- error: e,
1916
- handler: obj.name
1917
- };
1918
-
1919
- results.push(error_result);
1920
- ctx.results.push(error_result);
1921
- };
1922
-
1923
- /**
1924
- * 并行执行事件(提高性能)
1925
- * @param {string} key 事件关键字,支持space:key格式
1926
- * @param {object} params 传递参数
1927
- * @returns {Promise<object>} 返回包含results和cancel方法的对象
1928
- */
1929
- Eventer.prototype.runParallel = async function (key, ...params) {
1930
- let result = await this._execute(key, {
1931
- exec_mode: 'parallel',
1932
- options: params.options
1933
- }, ...params);
1934
- return {
1935
- results: result.results,
1936
- cancelled: result.cancelled,
1937
- cancel: result.cancel
1938
- };
1939
- };
1940
-
1941
- /**
1942
- * 并行触发事件
1943
- * @param {string} key 事件关键字,支持space:key格式
1944
- * @param {object} params 传递参数
1945
- * @returns {Promise<object>} 返回包含results和cancel方法的对象
1946
- */
1947
- Eventer.prototype.emitParallel = function (key, ...params) {
1948
- // 内部调用 _execute 方法,但不等待结果
1949
- let result = this._execute(key, {
1950
- exec_mode: 'parallel',
1951
- options: params.options
1952
- }, ...params);
1953
- result.catch(e => this.log('error', '事件并行执行失败:', e));
1954
- return {
1955
- ...result,
1956
- cancel: () => result.then(r => r && typeof r.cancel === 'function' && r.cancel())
1957
- };
1958
- };
1959
-
1960
- /**
1961
- * 防止内存泄漏警告
1962
- * @param {number} max_listen 最大监听器数量
1963
- * @returns {Eventer} 返回当前实例,支持链式调用
1964
- */
1965
- Eventer.prototype.setMaxListeners = function (max_listen) {
1966
- if (typeof max_listen !== 'number' || max_listen < 0) {
1967
- throw new Error('最大监听器数量必须是一个非负数');
1968
- }
1969
- this._max_listeners = max_listen;
1970
- return this;
1971
- };
1972
-
1973
- /**
1974
- * 批量添加事件
1975
- * @param {object} events_map 事件映射对象 { key: [func1, func2...] 或 key: {func, options} }
1976
- * @returns {Eventer} 返回当前实例,支持链式调用
1977
- */
1978
- Eventer.prototype.onMany = function (events_map) {
1979
- if (typeof events_map !== 'object' || events_map === null) {
1980
- throw new Error('事件对象必须是一个非空对象');
1981
- }
1982
-
1983
- for (let event_name in events_map) {
1984
- if (Object.prototype.hasOwnProperty.call(events_map, event_name)) {
1985
- this.on(event_name, events_map[event_name]);
1986
- }
1987
- }
1988
- return this;
1989
- };
1990
-
1991
- // 私有方法
1992
-
1993
- /**
1994
- * 解析事件键,提取命名空间和事件键
1995
- * @param {string} key 事件关键字
1996
- * @returns {object} 包含space和key的对象
1997
- * @private
1998
- */
1999
- Eventer.prototype._parseKey = function (key) {
2000
- let parts = key.split(':');
2001
- if (parts.length === 1) {
2002
- // 没有命名空间,使用默认命名空间
2003
- return {
2004
- space: this.config.default_name,
2005
- key: key
2006
- };
2007
- } else if (parts.length === 2) {
2008
- // 有命名空间
2009
- return {
2010
- space: parts[0],
2011
- key: parts[1]
2012
- };
2013
- } else {
2014
- // 多个冒号,将第一个作为命名空间,其余作为事件键
2015
- return {
2016
- space: parts[0],
2017
- key: parts.slice(1).join(':')
2018
- };
2019
- }
2020
- };
2021
-
2022
- /**
2023
- * 按优先级对事件列表进行排序
2024
- * @param {Array} events 事件列表
2025
- * @private
2026
- */
2027
- Eventer.prototype._sort = function (events) {
2028
- events.sort((a, b) => a.priority - b.priority);
2029
- };
2030
-
2031
- /**
2032
- * 运行中间件
2033
- * @param {string} type 中间件类型:'before' 或 'after'
2034
- * @param {object} ctx 上下文对象
2035
- * @private
2036
- */
2037
- Eventer.prototype._runMiddleware = async function (type, ctx) {
2038
- if (!this._middleware || !this._middleware[type] || this._middleware[type].length === 0) return;
2039
-
2040
- const mwList = this._middleware[type];
2041
- for (let i = 0; i < mwList.length; i++) {
2042
- await this._execMiddleware(mwList[i], type, ctx, i);
2043
- // 如果上下文被取消,则停止执行
2044
- if (ctx.cancelled) break;
2045
- }
2046
- };
2047
-
2048
- Eventer.prototype._execMiddleware = async function (middleware, type, ctx, idx) {
2049
- if (middleware && typeof middleware[type] === 'function') {
2050
- try {
2051
- await middleware[type].call(this, ctx);
2052
- } catch (middleware_error) {
2053
- this._handleMwareError(middleware_error, type, idx, ctx);
2054
- }
2055
- }
2056
- };
2057
-
2058
- Eventer.prototype._handleMwareError = function (middleware_error, type, index, ctx) {
2059
- this.log('error', `中间件执行失败 [${type}] - 索引:${index}`, middleware_error);
2060
-
2061
- // 全局错误处理器
2062
- if (this.config.error_handler && typeof this.config.error_handler === 'function') {
2063
- try {
2064
- this.config.error_handler(middleware_error, {
2065
- type: 'middleware',
2066
- stage: type,
2067
- index: index,
2068
- ctx
2069
- });
2070
- } catch (handler_error) {
2071
- this.log('error', '全局错误处理器执行失败', handler_error);
2072
- }
2073
- }
2074
- };
2075
-
2076
- /**
2077
- * 触发下一级事件链
2078
- * @param {string} current_event 当前事件键
2079
- * @param {Array} params 参数数组
2080
- * @private
2081
- */
2082
- Eventer.prototype._triggerChain = async function (current_event, params) {
2083
- // 获取当前事件的下级事件列表
2084
- var next_events = this._chain[current_event];
2085
- if (!next_events || next_events.length === 0) return;
2086
-
2087
- // 遍历并触发所有下级事件
2088
- for (var i = 0; i < next_events.length; i++) {
2089
- await this._triggerChainEvent(next_events[i], current_event, params);
2090
- }
2091
- };
2092
-
2093
- Eventer.prototype._triggerChainEvent = async function (key, current_event, params) {
2094
- // 避免重复执行当前事件
2095
- if (key === current_event) return;
2096
-
2097
- // 创建下级事件的上下文
2098
- var ctx = this._createChainCtx(key, current_event, params);
2099
-
2100
- // 执行前置中间件
2101
- await this._runChainMware('before', ctx);
2102
- if (ctx.cancelled) return;
2103
-
2104
- // 触发下级事件
2105
- await this._executeChainEvent(key, params, ctx);
2106
-
2107
- // 执行后置中间件
2108
- await this._runChainMware('after', ctx);
2109
-
2110
- // 递归触发下级事件的下级事件
2111
- if (!ctx.cancelled) {
2112
- await this._triggerChain(ctx.full_event, params);
2113
- }
2114
- };
2115
-
2116
- Eventer.prototype._createChainCtx = function (key, current_event, params) {
2117
- var { space, key: innerkey } = this._parseKey(key);
2118
- var fullkey = `${space}:${innerkey}`;
2119
-
2120
- return {
2121
- space,
2122
- event: innerkey,
2123
- full_event: fullkey,
2124
- params,
2125
- parent_event: current_event,
2126
- start_time: Date.now(),
2127
- executed: 0,
2128
- error_count: 0,
2129
- cancelled: false,
2130
- /**
2131
- * 取消事件执行
2132
- */
2133
- cancel: () => { this.cancelled = true; }
2134
- };
2135
- };
2136
-
2137
- Eventer.prototype._runChainMware = async function (type, ctx) {
2138
- try {
2139
- if (type === 'after') {
2140
- ctx.end_time = Date.now();
2141
- ctx.duration = ctx.end_time - ctx.start_time;
2142
- }
2143
- await this._runMiddleware(type, ctx);
2144
- } catch (error) {
2145
- this.log('error', `下级事件${type}中间件执行失败 [${ctx.full_event}]`, error);
2146
- }
2147
- };
2148
-
2149
- Eventer.prototype._executeChainEvent = async function (key, params, ctx) {
2150
- try {
2151
- await this.run(key, ...params);
2152
- } catch (event_error) {
2153
- this.log('error', `下级事件执行失败 [${ctx.full_event}]`, event_error);
2154
- }
2155
- };
2156
-
2157
- /**
2158
- * 节流函数
2159
- * @param {Function} func 要节流的函数
2160
- * @param {number} limit 节流时间(毫秒)
2161
- * @returns {Function} 节流后的函数
2162
- * @private
2163
- */
2164
- Eventer.prototype._throttle = function (func, limit) {
2165
- let last_func;
2166
- let last_time = 0;
2167
- return function () {
2168
- let ctx = this;
2169
- let args = arguments;
2170
- if (!last_time) {
2171
- func.apply(ctx, args);
2172
- last_time = Date.now();
2173
- } else {
2174
- clearTimeout(last_func);
2175
- last_func = setTimeout(() => {
2176
- if ((Date.now() - last_time) >= limit) {
2177
- func.apply(ctx, args);
2178
- last_time = Date.now();
2179
- }
2180
- }, limit - (Date.now() - last_time));
2181
- }
2182
- };
2183
- };
2184
-
2185
- /**
2186
- * 防抖函数
2187
- * @param {Function} func 要防抖的函数
2188
- * @param {number} wait 防抖时间(毫秒)
2189
- * @returns {Function} 防抖后的函数
2190
- * @private
2191
- */
2192
- Eventer.prototype._debounce = function (func, wait) {
2193
- let timeout;
2194
- return function () {
2195
- let ctx = this;
2196
- let args = arguments;
2197
- clearTimeout(timeout);
2198
- timeout = setTimeout(() => {
2199
- func.apply(ctx, args);
2200
- }, wait);
2201
- };
2202
- };
2203
-
2204
-
2205
- /**
2206
- * 暂停事件执行
2207
- * @param {string} key 事件关键字或命名空间,支持space:key格式,为空表示全局暂停
2208
- * @returns {boolean} 是否成功暂停
2209
- */
2210
- Eventer.prototype.pause = function (key = '') {
2211
- if (!this.config.pause_enabled) {
2212
- this.log('warn', '暂停功能未启用');
2213
- return false;
2214
- }
2215
-
2216
- if (!key) {
2217
- return this._pauseGlobal();
2218
- }
2219
-
2220
- // 解析关键字
2221
- let parsed = this._parseKey(key);
2222
- let space = parsed.space;
2223
- let event_key = parsed.key;
2224
- let full_key = `${space}:${event_key}`;
2225
-
2226
- if (key) {
2227
- return this._pauseEvent(full_key);
2228
- } else {
2229
- return this._pauseNamespace(space);
2230
- }
2231
- };
2232
-
2233
- Eventer.prototype._pauseGlobal = function () {
2234
- if (this._paused_global) {
2235
- this.log('warn', '事件总线已处于全局暂停状态');
2236
- return false;
2237
- }
2238
- this._paused_global = true;
2239
- this.log('info', '事件总线已全局暂停');
2240
- return true;
2241
- };
2242
-
2243
- Eventer.prototype._pauseEvent = function (full_key) {
2244
- if (this._paused.has(full_key)) {
2245
- this.log('warn', `事件 '${full_key}' 已处于暂停状态`);
2246
- return false;
2247
- }
2248
- this._paused.add(full_key);
2249
- this.log('info', `事件 '${full_key}' 已暂停`);
2250
- return true;
2251
- };
2252
-
2253
- Eventer.prototype._pauseNamespace = function (space) {
2254
- if (this._paused_space.has(space)) {
2255
- this.log('warn', `命名空间 '${space}' 已处于暂停状态`);
2256
- return false;
2257
- }
2258
- this._paused_space.add(space);
2259
- this.log('info', `命名空间 '${space}' 已暂停`);
2260
- return true;
2261
- };
2262
-
2263
- /**
2264
- * 恢复事件执行
2265
- * @param {string} key 事件关键字或命名空间,支持space:key格式,为空表示恢复全局暂停
2266
- * @returns {boolean} 是否成功恢复
2267
- */
2268
- Eventer.prototype.resume = function (key = '') {
2269
- if (!this.config.pause_enabled) {
2270
- this.log('warn', '暂停功能未启用');
2271
- return false;
2272
- }
2273
-
2274
- if (!key) {
2275
- return this._resumeGlobal();
2276
- }
2277
-
2278
- // 解析关键字
2279
- let parsed = this._parseKey(key);
2280
- let space = parsed.space;
2281
- let event_key = parsed.key;
2282
- let full_key = `${space}:${event_key}`;
2283
-
2284
- if (key) {
2285
- return this._resumeEvent(full_key);
2286
- } else {
2287
- return this._resumeNamespace(space);
2288
- }
2289
- };
2290
-
2291
- Eventer.prototype._resumeGlobal = function () {
2292
- if (!this._paused_global) {
2293
- this.log('warn', '事件总线未处于全局暂停状态');
2294
- return false;
2295
- }
2296
- this._paused_global = false;
2297
- this.log('info', '事件总线已恢复运行');
2298
- return true;
2299
- };
2300
-
2301
- Eventer.prototype._resumeEvent = function (full_key) {
2302
- if (!this._paused.has(full_key)) {
2303
- this.log('warn', `事件 '${full_key}' 未处于暂停状态`);
2304
- return false;
2305
- }
2306
- this._paused.delete(full_key);
2307
- this.log('info', `事件 '${full_key}' 已恢复`);
2308
- return true;
2309
- };
2310
-
2311
- Eventer.prototype._resumeNamespace = function (space) {
2312
- if (!this._paused_space.has(space)) {
2313
- this.log('warn', `命名空间 '${space}' 未处于暂停状态`);
2314
- return false;
2315
- }
2316
- this._paused_space.delete(space);
2317
- this.log('info', `命名空间 '${space}' 已恢复`);
2318
- return true;
2319
- };
2320
-
2321
- /**
2322
- * 检查事件是否被暂停
2323
- * @param {string} key 事件关键字,支持space:key格式
2324
- * @returns {boolean} 是否被暂停
2325
- */
2326
- Eventer.prototype.isPaused = function (key) {
2327
- if (!this.config.pause_enabled) {
2328
- return false;
2329
- }
2330
-
2331
- // 全局暂停检查
2332
- if (this._paused_global) {
2333
- return true;
2334
- }
2335
-
2336
- // 解析关键字
2337
- let parsed = this._parseKey(key);
2338
- let space = parsed.space;
2339
- let event_key = parsed.key;
2340
- let full_key = `${space}:${event_key}`;
2341
-
2342
- // 命名空间暂停检查
2343
- if (this._paused_space.has(space)) {
2344
- return true;
2345
- }
2346
-
2347
- // 单个事件暂停检查
2348
- if (this._paused.has(full_key)) {
2349
- return true;
2350
- }
2351
-
2352
- return false;
2353
- };
2354
-
2355
- /**
2356
- * 获取所有暂停的事件和命名空间
2357
- * @returns {object} 暂停状态信息
2358
- */
2359
- Eventer.prototype.getPausedStatus = function () {
2360
- return {
2361
- global_paused: this._paused_global,
2362
- paused_events: Array.from(this._paused),
2363
- paused_spaces: Array.from(this._paused_space)
2364
- };
2365
- };
2366
-
2367
- /**
2368
- * 清除所有暂停状态
2369
- * @returns {boolean} 是否成功清除
2370
- */
2371
- Eventer.prototype.clearPaused = function () {
2372
- if (!this.config.pause_enabled) {
2373
- this.log('warn', '暂停功能未启用');
2374
- return false;
2375
- }
2376
-
2377
- let cleared = false;
2378
-
2379
- if (this._paused_global) {
2380
- this._paused_global = false;
2381
- cleared = true;
2382
- }
2383
-
2384
- if (this._paused.size > 0) {
2385
- this._paused.clear();
2386
- cleared = true;
2387
- }
2388
-
2389
- if (this._paused_space.size > 0) {
2390
- this._paused_space.clear();
2391
- cleared = true;
2392
- }
2393
-
2394
- if (cleared) {
2395
- this.log('info', '所有暂停状态已清除');
2396
- }
2397
-
2398
- return cleared;
2399
- };
2400
-
2401
- let eventer = new Eventer();
2402
-
2403
- module.exports = {
2404
- Eventer,
2405
- eventer
2406
- };
1
+ /* eslint-disable mm_eslint/function-name */
2
+ require('./global.js');
3
+
4
+ /**
5
+ * 事件类 - 增强版EventBus实现
6
+ */
7
+ class Eventer {
8
+ static config = {
9
+ max_list: 10, // 最大监听器数量
10
+ default_name: 'default', // 默认命名空间
11
+ chain_enabled: true, // 是否启用链式触发
12
+ auto_clean: true, // 是否自动清理空的事件列表
13
+ error: null, // 全局错误处理函数
14
+ pause_enabled: true, // 是否启用暂停功能
15
+ };
16
+
17
+ // 日志对象
18
+ #logger = $.log || console;
19
+
20
+ /**
21
+ * 构造函数
22
+ * @param {object} config 配置参数
23
+ */
24
+ constructor(config) {
25
+ this.config = {
26
+ ...Eventer.config,
27
+ ...config || {}
28
+ };
29
+ // 是否为插件
30
+ this.is_plugin = false;
31
+ // 事件字典 - 支持命名空间
32
+ this._dict = {};
33
+ // 事件中间件
34
+ this._middleware = [];
35
+ // 命名空间映射
36
+ this._space = {};
37
+ // 事件链映射 { 'event1': ['event2', 'event3'], 'space:event1': ['event4'] }
38
+ this._chain = {};
39
+ // 进行中的任务映射,用于取消操作
40
+ this._tasks = new Map();
41
+ // 暂停状态管理
42
+ this._paused = new Set(); // 暂停的单个事件
43
+ this._paused_space = new Set(); // 暂停的命名空间
44
+ this._paused_global = false; // 全局暂停状态
45
+ // 初始化默认命名空间
46
+ this._space[this.config.default_name] = true;
47
+ }
48
+
49
+ /**
50
+ * 设置日志记录器
51
+ * @param {object} logger 日志记录器对象
52
+ */
53
+ setLogger(logger) {
54
+ this.#logger = logger;
55
+ }
56
+
57
+ /**
58
+ * 获取日志记录器
59
+ * @returns {object} 日志记录器对象
60
+ */
61
+ getLogger() {
62
+ return this.#logger;
63
+ }
64
+
65
+ /**
66
+ * 日志输出
67
+ * @param {string} level 日志级别
68
+ * @param {string} message 日志消息
69
+ * @param {...any} params 日志参数
70
+ */
71
+ log(level, message, ...params) {
72
+ this.getLogger()[level](`[${this.constructor.name}] ${message}`, ...params);
73
+ }
74
+ }
75
+
76
+ /**
77
+ * 初始化事件管理器
78
+ * @param {...any} args 初始化参数
79
+ * @returns {Eventer} 返回事件管理器实例
80
+ * @private
81
+ */
82
+ Eventer.prototype._init = async function (...args) {
83
+ // 初始化逻辑
84
+ return this;
85
+ };
86
+
87
+ /**
88
+ * 初始化事件管理器
89
+ * @param {...any} args 初始化参数
90
+ * @returns {Eventer} 返回事件管理器实例
91
+ */
92
+ Eventer.prototype.init = async function (...args) {
93
+ return this._init(...args);
94
+ };
95
+
96
+ /**
97
+ * 监听事件(支持命名空间和优先级)
98
+ * @param {string} key 事件关键字,支持space:key格式
99
+ * @param {object} func 触发函数
100
+ * @throws {Error} 事件关键字必须是非空字符串
101
+ * @throws {Error} 事件处理函数必须是一个函数
102
+ */
103
+ Eventer.prototype._validateOnParams = function (key, func) {
104
+ if (!key || typeof key !== 'string') {
105
+ throw new Error('事件关键字必须是非空字符串');
106
+ }
107
+ if (typeof func !== 'function') {
108
+ throw new Error('事件处理函数必须是一个函数');
109
+ }
110
+ };
111
+
112
+ Eventer.prototype._parseEventKey = function (key, ns) {
113
+ let parsed = this._parseKey(key);
114
+ let space = ns || parsed.space;
115
+ let event_key = parsed.key;
116
+ let full_key = `${space}:${event_key}`;
117
+ return { space, event_key, full_key };
118
+ };
119
+
120
+ Eventer.prototype._initNamespace = function (space, event_key) {
121
+ if (!this._dict[space]) {
122
+ this._dict[space] = {};
123
+ this._space[space] = true;
124
+ }
125
+ if (!this._dict[space][event_key]) {
126
+ this._dict[space][event_key] = [];
127
+ }
128
+ };
129
+
130
+ Eventer.prototype._generateDefaultName = function (func) {
131
+ return func.name || `handler_${Date.now()}_${Math.floor(Math.random() * 1000)}`;
132
+ };
133
+
134
+ Eventer.prototype._wrapFunction = function (func, params) {
135
+ let wrapped_func = func;
136
+
137
+ if (params.throttle) {
138
+ wrapped_func = this._throttle(func, params.throttle);
139
+ } else if (params.debounce) {
140
+ wrapped_func = this._debounce(func, params.debounce);
141
+ }
142
+
143
+ if (params.timeout && typeof params.timeout === 'number' && params.timeout > 0) {
144
+ let original_func = wrapped_func;
145
+ wrapped_func = async function (...args) {
146
+ const timeoutPromise = new Promise((resolve, reject) => {
147
+ setTimeout(() => reject(new Error(`事件执行超时 (${params.timeout}ms)`)), params.timeout);
148
+ });
149
+ return Promise.race([original_func.apply(this, args), timeoutPromise]);
150
+ };
151
+ }
152
+
153
+ return wrapped_func;
154
+ };
155
+
156
+ Eventer.prototype._createHandlerObj = function (config) {
157
+ var handler = {
158
+ name: config.name,
159
+ func: config.wrapped_func,
160
+ original_func: config.func,
161
+ times: config.times,
162
+ priority: config.priority,
163
+ created_at: Date.now(),
164
+ last_executed: null
165
+ };
166
+ return handler;
167
+ };
168
+
169
+ Eventer.prototype._findHandlerIndex = function (list, name) {
170
+ for (let i = 0; i < list.length; i++) {
171
+ if (list[i].name === name) {
172
+ return i;
173
+ }
174
+ }
175
+ return -1;
176
+ };
177
+
178
+ Eventer.prototype._checkListenerLimit = function (space, event_key, list) {
179
+ let max_list = this.config.max_list;
180
+ if (max_list > 0 && list.length >= max_list) {
181
+ this.log('warn', `警告: '${space}:${event_key}' 事件的监听器数量已达到 ${max_list},可能导致内存泄漏。使用 set_max_listeners() 方法可以增加限制。`);
182
+ }
183
+ };
184
+
185
+ Eventer.prototype._createHandlerResult = function (space, index, name, full_key) {
186
+ return {
187
+ space,
188
+ index,
189
+ name,
190
+ remove: () => this.off(full_key, name)
191
+ };
192
+ };
193
+
194
+ /**
195
+ * 监听事件(支持命名空间和优先级)
196
+ * @param {string} key 事件关键字,支持space:key格式
197
+ * @param {object} func 触发函数
198
+ * @param {string} name 增加名称,方便删除,当出现相同名称时会被覆盖
199
+ * @param {object} options 其他选项,如throttle、debounce、timeout等
200
+ * @returns {object} 返回事件信息对象 {space, index, name, remove},remove为移除该事件的函数
201
+ */
202
+ Eventer.prototype.on = function (key, func, name, options) {
203
+ // 处理参数
204
+ let params = this._processOnParams(key, func, name, options);
205
+
206
+ // 验证参数
207
+ this._validateOnParams(params.key, params.func);
208
+
209
+ // 处理事件添加
210
+ return this._addEventHandler(params);
211
+ };
212
+
213
+ Eventer.prototype._processOnParams = function (key, func, name, options) {
214
+ // 支持两种调用方式:便捷方式和配置对象方式
215
+ if (typeof key === 'object' && key !== null) {
216
+ // 配置对象方式
217
+ return this._extractOnParams(key);
218
+ } else {
219
+ // 便捷方式
220
+ let opts = options || {};
221
+ return {
222
+ key: key,
223
+ func: func,
224
+ name: name,
225
+ times: opts.times || -1,
226
+ priority: opts.priority || 0,
227
+ ns: opts.ns || null
228
+ };
229
+ }
230
+ };
231
+
232
+ Eventer.prototype._addEventHandler = function (params) {
233
+ const { key: event_key, func: event_func, name: event_name,
234
+ times: event_times, priority: event_priority, ns } = params;
235
+
236
+ // 解析命名空间
237
+ const { space, event_key: parsed_event_key, full_key } = this._parseEventKey(event_key, ns);
238
+
239
+ // 初始化命名空间和事件数组
240
+ this._initNamespace(space, parsed_event_key);
241
+
242
+ // 设置默认名称
243
+ let final_name = event_name || this._generateDefaultName(event_func);
244
+
245
+ // 应用节流或防抖
246
+ let wrapped_func = this._wrapFunction(event_func, params);
247
+
248
+ // 创建事件对象
249
+ let obj = this._createHandlerObj({
250
+ name: final_name,
251
+ wrapped_func: wrapped_func,
252
+ func: event_func,
253
+ times: event_times,
254
+ priority: event_priority
255
+ });
256
+
257
+ // 处理事件添加逻辑
258
+ return this._handleEventAddition({ space, event_key: parsed_event_key, full_key, final_name, obj });
259
+ };
260
+
261
+ Eventer.prototype._extractOnParams = function (config) {
262
+ return {
263
+ key: config.key,
264
+ func: config.func,
265
+ name: config.name,
266
+ times: config.times || -1,
267
+ priority: config.priority || 0,
268
+ ns: config.ns || null
269
+ };
270
+ };
271
+
272
+ Eventer.prototype._processOnceParams = function (key, func, name, options) {
273
+ // 支持两种调用方式:便捷方式和配置对象方式
274
+ if (typeof key === 'object' && key !== null) {
275
+ // 配置对象方式
276
+ let params = this._extractOnParams(key);
277
+ params.times = 1; // 强制设置为仅执行一次
278
+ return params;
279
+ } else {
280
+ // 便捷方式
281
+ let opts = options || {};
282
+ return {
283
+ key: key,
284
+ func: func,
285
+ name: name,
286
+ times: 1, // 强制设置为仅执行一次
287
+ priority: opts.priority || 0,
288
+ ns: opts.ns || null
289
+ };
290
+ }
291
+ };
292
+
293
+ Eventer.prototype._handleEventAddition = function (config) {
294
+ const { space, event_key, full_key, final_name, obj } = config;
295
+ let list = this._dict[space][event_key];
296
+ let idx = this._findHandlerIndex(list, final_name);
297
+
298
+ if (idx >= 0) {
299
+ // 覆盖已存在的同名监听器
300
+ Object.assign(list[idx], obj);
301
+ // 重新排序
302
+ this._sort(list);
303
+ return this._createHandlerResult(space, idx, final_name, full_key);
304
+ } else {
305
+ // 检查监听器数量是否超过限制
306
+ this._checkListenerLimit(space, event_key, list);
307
+
308
+ // 添加新事件
309
+ list.push(obj);
310
+ // 按优先级排序
311
+ this._sort(list);
312
+ return this._createHandlerResult(space, list.length - 1, final_name, full_key);
313
+ }
314
+ };
315
+
316
+ /**
317
+ * 监听事件(仅执行一次)
318
+ * @param {string | object} key 事件关键,支持space:key格式,或配置对象
319
+ * @param {object} func 触发函数
320
+ * @param {string} name 增加名称,方便删除,当出现相同名称时会被覆盖
321
+ * @param {object} options 其他选项
322
+ * @returns {object} 返回事件信息对象 {space, idx, name}
323
+ */
324
+ Eventer.prototype.once = function (key, func, name, options) {
325
+ // 处理参数
326
+ let params = this._processOnceParams(key, func, name, options);
327
+
328
+ // 验证参数
329
+ this._validateOnParams(params.key, params.func);
330
+
331
+ // 处理事件添加
332
+ return this._addEventHandler(params);
333
+ };
334
+
335
+ /**
336
+ * 统一的事件执行引擎
337
+ * @param {string} key 事件关键字,支持space:key格式
338
+ * @throws {Error} 事件关键字必须是非空字符串
339
+ * @private
340
+ */
341
+ Eventer.prototype._validateExec = function (key) {
342
+ if (!key || typeof key !== 'string') {
343
+ throw new Error('事件关键字必须是非空字符串');
344
+ }
345
+ };
346
+
347
+ Eventer.prototype._createCtx = function (key, params) {
348
+ let parsed = this._parseKey(key);
349
+ let space = parsed.space;
350
+ let event_key = parsed.key;
351
+ let full_key = `${space}:${event_key}`;
352
+ let start_time = Date.now();
353
+
354
+ const ctx = {
355
+ space,
356
+ event: event_key,
357
+ full_event: full_key,
358
+ params,
359
+ results: [],
360
+ start_time: start_time,
361
+ executed: 0,
362
+ error_count: 0,
363
+ cancelled: false,
364
+ cancel: () => {
365
+ ctx.cancelled = true;
366
+ this._cancelTasks(full_key);
367
+ }
368
+ };
369
+
370
+ return { ctx, space, event_key, full_key, start_time };
371
+ };
372
+
373
+ Eventer.prototype._cancelTasks = function (full_key) {
374
+ try {
375
+ if (this._tasks.has(full_key)) {
376
+ let tasks = this._tasks.get(full_key);
377
+ tasks.forEach(task => {
378
+ if (task && typeof task.cancel === 'function') {
379
+ try {
380
+ task.cancel();
381
+ } catch (cancel_error) {
382
+ this.log('error', `任务取消失败 [${full_key}] - ${task.id}`, cancel_error);
383
+ }
384
+ }
385
+ });
386
+ this._tasks.delete(full_key);
387
+ }
388
+ } catch (cancel_global_error) {
389
+ this.log('error', `任务取消过程异常 [${full_key}]`, cancel_global_error);
390
+ }
391
+ };
392
+
393
+ Eventer.prototype._initTaskList = function (full_key) {
394
+ try {
395
+ this._tasks.set(full_key, []);
396
+ } catch (task_init_error) {
397
+ this.log('error', `任务列表初始化失败 [${full_key}]`, task_init_error);
398
+ }
399
+ };
400
+
401
+ Eventer.prototype._runBeforeMiddleware = async function (ctx, full_key) {
402
+ try {
403
+ await this._runMiddleware('before', ctx);
404
+ if (ctx.cancelled) {
405
+ this._cleanupTasks(full_key);
406
+ return true;
407
+ }
408
+ return false;
409
+ } catch (error) {
410
+ this.log('error', `事件中间件执行失败 [${ctx.space}:${ctx.event}]`, error);
411
+ if (this.config.error_handler && typeof this.config.error_handler === 'function') {
412
+ this.config.error_handler(error, { type: 'middleware', stage: 'before', ctx });
413
+ }
414
+ return false;
415
+ }
416
+ };
417
+
418
+ Eventer.prototype._cleanupTasks = function (full_key) {
419
+ try {
420
+ this._tasks.delete(full_key);
421
+ } catch (cleanup_error) {
422
+ this.log('error', `任务清理失败 [${full_key}]`, cleanup_error);
423
+ }
424
+ };
425
+
426
+ Eventer.prototype._executeStrategy = async function (config) {
427
+ const { list, params, ctx, full_key, arr, options } = config;
428
+
429
+ try {
430
+ if (options.exec_mode === 'parallel') {
431
+ await this._executeParallel({ list, params, ctx, full_key, arr });
432
+ } else if (options.exec_mode === 'race') {
433
+ ctx.race_result = await this._executeRace({ list, params, ctx, full_key, arr });
434
+ } else if (options.exec_mode === 'waterfall') {
435
+ await this._executeWaterfall({
436
+ list, params, ctx, full_key, arr,
437
+ initial_value: options.initial_value
438
+ });
439
+ } else {
440
+ await this._executeSequential({ list, params, ctx, full_key, arr });
441
+ }
442
+ } catch (exec_error) {
443
+ this.log('error', `事件执行策略异常 [${full_key}]`, exec_error);
444
+ if (this.config.error_handler && typeof this.config.error_handler === 'function') {
445
+ this.config.error_handler(exec_error, { type: 'execution', ctx });
446
+ }
447
+ }
448
+ };
449
+
450
+ Eventer.prototype._removeEvents = function (space, key, arr) {
451
+ try {
452
+ for (let i = 0; i < arr.length; i++) {
453
+ this.del(`${space}:${key}`, arr[i]);
454
+ }
455
+ } catch (remove_error) {
456
+ this.log('error', `事件移除失败 [${space}:${key}]`, remove_error);
457
+ }
458
+ };
459
+
460
+ Eventer.prototype._autoCleanup = function (space, key) {
461
+ try {
462
+ if (this.config.auto_clean && this._dict[space] && this._dict[space][key] &&
463
+ this._dict[space][key].length === 0) {
464
+ delete this._dict[space][key];
465
+ if (this._dict[space] && Object.keys(this._dict[space]).length === 0) {
466
+ delete this._dict[space];
467
+ delete this._space[space];
468
+ }
469
+ }
470
+ } catch (cleanup_error) {
471
+ this.log('error', `自动清理失败 [${space}:${key}]`, cleanup_error);
472
+ }
473
+ };
474
+
475
+ Eventer.prototype._runAfterMiddleware = async function (ctx, start_time) {
476
+ try {
477
+ ctx.end_time = Date.now();
478
+ ctx.duration = ctx.end_time - start_time;
479
+ await this._runMiddleware('after', ctx);
480
+ } catch (error) {
481
+ this.log('error', `事件后置中间件执行失败 [${ctx.space}:${ctx.event}]`, error);
482
+ if (this.config.error_handler && typeof this.config.error_handler === 'function') {
483
+ this.config.error_handler(error, { type: 'middleware', stage: 'after', ctx });
484
+ }
485
+ }
486
+ };
487
+
488
+ Eventer.prototype._executeEventChain = async function (ctx, full_key, params) {
489
+ if (!ctx.cancelled && this.config.chain_enabled && this._chain[full_key]) {
490
+ try {
491
+ await this._triggerChain(full_key, params);
492
+ } catch (chain_error) {
493
+ this.log('error', `事件链执行失败 [${full_key}]`, chain_error);
494
+ if (this.config.error_handler && typeof this.config.error_handler === 'function') {
495
+ this.config.error_handler(chain_error, { type: 'chain', ctx });
496
+ }
497
+ }
498
+ }
499
+ };
500
+
501
+ Eventer.prototype._buildSafeResult = function (ctx) {
502
+ try {
503
+ return {
504
+ results: ctx.results || [],
505
+ cancelled: ctx.cancelled || false,
506
+ cancel: ctx.cancel || (() => { }),
507
+ race: ctx.race_result,
508
+ waterfall: ctx.results && ctx.results.length > 0 ? ctx.results[ctx.results.length - 1]
509
+ : undefined
510
+ };
511
+ } catch (return_error) {
512
+ this.log('error', `结果构造失败 [${ctx.full_event}]`, return_error);
513
+ return {
514
+ results: [],
515
+ cancelled: true,
516
+ cancel: () => { },
517
+ error: return_error
518
+ };
519
+ }
520
+ };
521
+
522
+ Eventer.prototype._execute = async function (key, options = {}, ...params) {
523
+ this._validateExec(key);
524
+
525
+ const { ctx, space, event_key, full_key, start_time } = this._createCtx(key, params);
526
+
527
+ if (this.isPaused(full_key)) {
528
+ return this._createPausedResult();
529
+ }
530
+
531
+ let list = this._dict[space] && this._dict[space][event_key];
532
+ const arr = [];
533
+
534
+ if (list && list.length > 0) {
535
+ await this._executeEventList({
536
+ list, params, ctx, full_key, arr, options, space, event_key, start_time
537
+ });
538
+ }
539
+
540
+ await this._executeEventChain(ctx, full_key, params);
541
+ return this._buildSafeResult(ctx);
542
+ };
543
+
544
+ /**
545
+ * 创建暂停状态的结果对象
546
+ * @returns {object} 暂停状态的结果
547
+ * @private
548
+ */
549
+ Eventer.prototype._createPausedResult = function () {
550
+ return {
551
+ results: [],
552
+ cancelled: false,
553
+ paused: true,
554
+ /**
555
+ * 取消函数
556
+ */
557
+ cancel: () => { }
558
+ };
559
+ };
560
+
561
+ /**
562
+ * 执行事件列表
563
+ * @param {object} config 配置参数
564
+ * @param {Array} config.list 事件列表
565
+ * @param {Array} config.params 参数
566
+ * @param {object} config.ctx 上下文
567
+ * @param {string} config.full_key 完整键名
568
+ * @param {Array} config.arr 数组
569
+ * @param {object} config.options 选项
570
+ * @param {string} config.space 命名空间
571
+ * @param {string} config.event_key 事件键
572
+ * @param {number} config.start_time 开始时间
573
+ * @param {string} config.strategy 执行策略,默认sequential
574
+ * @returns {object} 返回执行结果
575
+ * @private
576
+ */
577
+ Eventer.prototype._executeEventList = async function (config) {
578
+ const { list, params, ctx, full_key, arr, options, space, event_key, start_time } = config;
579
+
580
+ this._initTaskList(full_key);
581
+
582
+ let cancelled = await this._runBeforeMiddleware(ctx, full_key);
583
+ if (cancelled) {
584
+ return {
585
+ results: [],
586
+ cancelled: true,
587
+ cancel: ctx.cancel
588
+ };
589
+ }
590
+
591
+ await this._executeStrategy({ list, params, ctx, full_key, arr, options });
592
+
593
+ this._cleanupTasks(full_key);
594
+ this._removeEvents(space, event_key, arr);
595
+ this._autoCleanup(space, event_key);
596
+ await this._runAfterMiddleware(ctx, start_time);
597
+ };
598
+
599
+ /**
600
+ * 顺序执行事件处理函数
601
+ * @param {object} config 配置参数
602
+ * @private
603
+ */
604
+ Eventer.prototype._executeSequential = async function (config) {
605
+ const { list, params, ctx, full_key, arr } = config;
606
+
607
+ for (let i = 0; i < list.length && !ctx.cancelled; i++) {
608
+ let o = list[i];
609
+ ctx.executed++;
610
+ o.last_executed = Date.now();
611
+
612
+ // 创建并执行单个任务
613
+ await this._execSingleTask(o, params, ctx, { full_key, arr });
614
+ }
615
+ };
616
+
617
+ Eventer.prototype._execSingleTask = async function (o, params, ctx, options) {
618
+ const { full_key, arr } = options;
619
+
620
+ // 创建任务
621
+ let task = this._createTask(o, full_key);
622
+
623
+ try {
624
+ // 执行事件处理函数
625
+ let result = await o.func.apply(o, params);
626
+
627
+ // 处理成功结果
628
+ this._handleSuccessResult({ result, o, ctx, arr, task });
629
+ } catch (e) {
630
+ // 处理错误
631
+ this._handleSeqTaskError(e, o, ctx, task);
632
+ }
633
+ };
634
+
635
+ Eventer.prototype._createTask = function (o, full_key) {
636
+ let task_id = `${o.name}_${Date.now()}`;
637
+ let cancelled = false;
638
+ const task = {
639
+ id: task_id,
640
+ cancel: () => { cancelled = true; }
641
+ };
642
+
643
+ // 添加到进行中的任务列表(防御性处理重入调用导致 key 已被清理的情况)
644
+ let tasks = this._tasks.get(full_key);
645
+ if (!tasks) {
646
+ tasks = [];
647
+ this._tasks.set(full_key, tasks);
648
+ }
649
+ tasks.push(task);
650
+
651
+ return { task, tasks, cancelled };
652
+ };
653
+
654
+ Eventer.prototype._handleSuccessResult = function (config) {
655
+ const { result, o, ctx, arr, task } = config;
656
+
657
+ // 如果任务已取消,则不添加结果
658
+ if (!task.cancelled && !ctx.cancelled) {
659
+ ctx.results.push(result);
660
+
661
+ // 处理执行次数限制
662
+ if (o.times >= 0) {
663
+ o.times--;
664
+ if (o.times <= 0) {
665
+ arr.push(o.name);
666
+ }
667
+ }
668
+ }
669
+
670
+ // 从进行中的任务列表中移除
671
+ task.tasks.splice(task.tasks.indexOf(task.task), 1);
672
+ };
673
+
674
+ Eventer.prototype._handleSeqTaskError = function (e, o, ctx, task) {
675
+ ctx.error_count++;
676
+ this.log('error', `事件执行失败 [${ctx.space}:${ctx.event}] - ${o.name}`, e);
677
+
678
+ const error_result = {
679
+ _error: true,
680
+ error: e,
681
+ handler: o.name,
682
+ timestamp: Date.now()
683
+ };
684
+
685
+ ctx.results.push(error_result);
686
+
687
+ // 全局错误处理器
688
+ if (this.config.error_handler && typeof this.config.error_handler === 'function') {
689
+ this.config.error_handler(e, { type: 'handler', handler: o.name, ctx });
690
+ }
691
+
692
+ // 从进行中的任务列表中移除
693
+ task.tasks.splice(task.tasks.indexOf(task.task), 1);
694
+ };
695
+
696
+ /**
697
+ * 并行执行事件处理函数
698
+ * @param {object} config 配置参数
699
+ * @private
700
+ */
701
+ Eventer.prototype._executeParallel = async function (config) {
702
+ const { list, params, ctx, full_key, arr } = config;
703
+ let concurrency = this._getConcurrency(params);
704
+ // eslint-disable-next-line mm_eslint/class-instance-name
705
+ const proc_results = new Array(list.length);
706
+
707
+ if (concurrency < Infinity) {
708
+ await this._executeBatches({
709
+ list, params, ctx, full_key, arr, concurrency, proc_results
710
+ });
711
+ } else {
712
+ await this._executeAllParallel({ list, params, ctx, full_key, arr, proc_results });
713
+ }
714
+
715
+ this._setResults(ctx, proc_results);
716
+ };
717
+
718
+ Eventer.prototype._getConcurrency = function (params) {
719
+ return params.options && typeof params.options.concurrency === 'number' ?
720
+ params.options.concurrency : Infinity;
721
+ };
722
+
723
+ Eventer.prototype._executeBatches = async function (config) {
724
+ const { list, params, ctx, full_key, arr, concurrency, proc_results } = config;
725
+
726
+ for (let i = 0; i < list.length && !ctx.cancelled; i += concurrency) {
727
+ let batch = list.slice(i, i + concurrency);
728
+ let batch_promises = batch.map((obj, batch_idx) => {
729
+ let global = i + batch_idx;
730
+ return this._executeSingleTask({
731
+ obj, params, ctx, full_key, arr, idx: global, proc_results
732
+ });
733
+ });
734
+
735
+ await Promise.allSettled(batch_promises);
736
+ }
737
+ };
738
+
739
+ Eventer.prototype._executeAllParallel = async function (config) {
740
+ const { list, params, ctx, full_key, arr, proc_results } = config;
741
+
742
+ let promises = list.map((obj, idx) => {
743
+ return this._executeSingleTask({ obj, params, ctx, full_key, arr, idx, proc_results });
744
+ });
745
+
746
+ await Promise.allSettled(promises);
747
+ };
748
+
749
+ Eventer.prototype._setResults = function (ctx, proc_results) {
750
+ ctx.results = proc_results.filter(result => result !== undefined);
751
+ };
752
+
753
+ /**
754
+ * 瀑布流执行事件处理函数
755
+ * @param {object} config 配置参数
756
+ * @private
757
+ */
758
+ Eventer.prototype._executeWaterfall = async function (config) {
759
+ const { list, params, ctx, full_key, arr, initial_value } = config;
760
+ let wate_value = this._getInitialValue(params, initial_value);
761
+
762
+ for (let i = 0; i < list.length && !ctx.cancelled; i++) {
763
+ let obj = list[i];
764
+ ctx.executed++;
765
+ obj.last_executed = Date.now();
766
+
767
+ let task = this._createWaterfallTask(obj, full_key);
768
+ wate_value = await this._execWaterfallStep({
769
+ obj, params, ctx, arr, task, wate_value
770
+ });
771
+ }
772
+ };
773
+
774
+ Eventer.prototype._getInitialValue = function (params, initial_value) {
775
+ return initial_value !== undefined ? initial_value : (params.length > 0 ? params[0] : undefined);
776
+ };
777
+
778
+ Eventer.prototype._createWaterfallTask = function (obj, full_key) {
779
+ let task_id = `${obj.name}_${Date.now()}`;
780
+ let cancelled = false;
781
+ const task = {
782
+ id: task_id,
783
+ cancel: () => { cancelled = true; }
784
+ };
785
+
786
+ let tasks = this._tasks.get(full_key);
787
+ if (!tasks) {
788
+ tasks = [];
789
+ this._tasks.set(full_key, tasks);
790
+ }
791
+ tasks.push(task);
792
+
793
+ return { task, tasks, cancelled };
794
+ };
795
+
796
+ Eventer.prototype._execWaterfallStep = async function (config) {
797
+ const { obj, params, ctx, arr, task, wate_value } = config;
798
+ try {
799
+ let result = await obj.func.apply(obj, [wate_value, ...params.slice(1)]);
800
+ this._handleWfSuccess({ result, obj, ctx, arr, task });
801
+ return result;
802
+ } catch (e) {
803
+ this._handleWfError({ e, obj, ctx, task });
804
+ return wate_value;
805
+ }
806
+ };
807
+
808
+ Eventer.prototype._handleWfSuccess = function (config) {
809
+ const { result, obj, ctx, arr, task } = config;
810
+ if (!task.cancelled && !ctx.cancelled) {
811
+ ctx.results.push(result);
812
+ this._handleTimesLimit(obj, arr);
813
+ }
814
+ this._removeTask(task);
815
+ };
816
+
817
+ Eventer.prototype._handleWfError = function (config) {
818
+ const { e, obj, ctx, task } = config;
819
+ ctx.error_count++;
820
+ this.log('error', `事件执行失败 [${ctx.space}:${ctx.event}] - ${obj.name}`, e);
821
+
822
+ const error_result = {
823
+ _error: true,
824
+ error: e,
825
+ handler: obj.name,
826
+ timestamp: Date.now()
827
+ };
828
+
829
+ ctx.results.push(error_result);
830
+ this._callErrorHandler(e, obj, ctx);
831
+ this._removeTask(task);
832
+ };
833
+
834
+ Eventer.prototype._handleTimesLimit = function (obj, arr) {
835
+ if (obj.times >= 0) {
836
+ obj.times--;
837
+ if (obj.times <= 0) {
838
+ arr.push(obj.name);
839
+ }
840
+ }
841
+ };
842
+
843
+ Eventer.prototype._removeTask = function (task) {
844
+ task.tasks.splice(task.tasks.indexOf(task.task), 1);
845
+ };
846
+
847
+ Eventer.prototype._callErrorHandler = function (e, obj, ctx) {
848
+ if (this.config.error_handler && typeof this.config.error_handler === 'function') {
849
+ this.config.error_handler(e, { type: 'handler', handler: obj.name, ctx });
850
+ }
851
+ };
852
+
853
+ /**
854
+ * 竞争执行模式 - 返回第一个完成的结果
855
+ * @param {object} config 配置参数
856
+ * @param {Array} config.list 事件列表
857
+ * @param {Array} config.params 参数
858
+ * @param {object} config.ctx 上下文
859
+ * @param {string} config.strategy 执行策略
860
+ * @returns {Promise<object>} 返回包含results和cancel方法的对象
861
+ * @private
862
+ */
863
+ Eventer.prototype._executeRace = async function (config) {
864
+ const { list, params, ctx, full_key, arr } = config;
865
+ let promises = this._createRacePromises({ list, params, ctx, full_key, arr });
866
+
867
+ return await this._runRace(promises);
868
+ };
869
+
870
+ Eventer.prototype._createRacePromises = function (config) {
871
+ const { list, params, ctx, full_key, arr } = config;
872
+ const promises = [];
873
+
874
+ for (let i = 0; i < list.length && !ctx.cancelled; i++) {
875
+ let obj = list[i];
876
+ ctx.executed++;
877
+ obj.last_executed = Date.now();
878
+
879
+ let promise = this._createRacePromise({ obj, params, ctx, full_key, arr });
880
+ promises.push(promise);
881
+ }
882
+
883
+ return promises;
884
+ };
885
+
886
+ Eventer.prototype._createRacePromise = function (config) {
887
+ const { obj, params, ctx, full_key, arr } = config;
888
+ let task = this._createRaceTask(obj, full_key);
889
+
890
+ return (async () => {
891
+ try {
892
+ let result = await obj.func.apply(obj, params);
893
+ return this._handleRaceSuccess({ result, obj, ctx, arr, task });
894
+ } catch (e) {
895
+ return this._handleRaceError(e, obj, ctx, task);
896
+ } finally {
897
+ this._removeTask(task);
898
+ }
899
+ })();
900
+ };
901
+
902
+ Eventer.prototype._createRaceTask = function (obj, full_key) {
903
+ let task_id = `${obj.name}_${Date.now()}`;
904
+ let cancelled = false;
905
+ const task = {
906
+ id: task_id,
907
+ cancel: () => { cancelled = true; }
908
+ };
909
+
910
+ let tasks = this._tasks.get(full_key);
911
+ if (!tasks) {
912
+ tasks = [];
913
+ this._tasks.set(full_key, tasks);
914
+ }
915
+ tasks.push(task);
916
+
917
+ return { task, tasks, cancelled };
918
+ };
919
+
920
+ Eventer.prototype._handleRaceSuccess = function (config) {
921
+ const { result, obj, ctx, arr, task } = config;
922
+
923
+ if (!task.cancelled && !ctx.cancelled) {
924
+ ctx.results.push(result);
925
+ this._handleTimesLimit(obj, arr);
926
+ return { success: true, result, handler: obj.name };
927
+ }
928
+ return { success: false, cancelled: true };
929
+ };
930
+
931
+ Eventer.prototype._handleRaceError = function (e, obj, ctx, task) {
932
+ ctx.error_count++;
933
+ this.log('error', `事件执行失败 [${ctx.space}:${ctx.event}] - ${obj.name}`, e);
934
+
935
+ const error_result = {
936
+ _error: true,
937
+ error: e,
938
+ handler: obj.name,
939
+ timestamp: Date.now()
940
+ };
941
+
942
+ ctx.results.push(error_result);
943
+ this._callErrorHandler(e, obj, ctx);
944
+
945
+ return { success: false, error: e, handler: obj.name };
946
+ };
947
+
948
+ Eventer.prototype._runRace = async function (promises) {
949
+ if (promises.length > 0) {
950
+ let race = await Promise.race(promises);
951
+ return race;
952
+ }
953
+ return null;
954
+ };
955
+
956
+ /**
957
+ * 执行单个任务(并行执行时使用)
958
+ * @param {object} config 配置参数
959
+ * @private
960
+ */
961
+ Eventer.prototype._executeSingleTask = async function (config) {
962
+ const { obj, params, ctx, full_key, arr, idx, proc_results } = config;
963
+ obj.last_executed = Date.now();
964
+
965
+ // 创建任务
966
+ let task_info = this._createParallelTask(obj, full_key);
967
+
968
+ try {
969
+ let result = await obj.func.apply(obj, params);
970
+ this._handleTaskSuccess({ result, obj, ctx, arr, idx, proc_results, task_info });
971
+ } catch (err) {
972
+ this._handleTaskError({ err, obj, ctx, idx, proc_results, task_info });
973
+ }
974
+ };
975
+
976
+ Eventer.prototype._createParallelTask = function (obj, full_key) {
977
+ let task_id = `${obj.name}_${Date.now()}`;
978
+ let cancelled = false;
979
+ const task = {
980
+ id: task_id,
981
+ cancel: () => { cancelled = true; }
982
+ };
983
+
984
+ // 添加到进行中的任务列表(防御性处理重入调用导致 key 已被清理的情况)
985
+ let tasks = this._tasks.get(full_key);
986
+ if (!tasks) {
987
+ tasks = [];
988
+ this._tasks.set(full_key, tasks);
989
+ }
990
+ tasks.push(task);
991
+
992
+ return { task, tasks, cancelled };
993
+ };
994
+
995
+ Eventer.prototype._handleTaskSuccess = function (config) {
996
+ const { result, obj, ctx, arr, idx, proc_results, task_info } = config;
997
+
998
+ // 从进行中的任务列表中移除
999
+ task_info.tasks.splice(task_info.tasks.indexOf(task_info.task), 1);
1000
+
1001
+ if (!task_info.cancelled && !ctx.cancelled) {
1002
+ proc_results[idx] = result;
1003
+
1004
+ // 处理执行次数限制
1005
+ if (obj.times >= 0) {
1006
+ obj.times--;
1007
+ if (obj.times <= 0) {
1008
+ arr.push(obj.name);
1009
+ }
1010
+ }
1011
+ }
1012
+ };
1013
+
1014
+ Eventer.prototype._handleTaskError = function (config) {
1015
+ const { err, obj, ctx, idx, proc_results, task_info } = config;
1016
+
1017
+ // 从进行中的任务列表中移除
1018
+ task_info.tasks.splice(task_info.tasks.indexOf(task_info.task), 1);
1019
+
1020
+ if (!task_info.cancelled && !ctx.cancelled) {
1021
+ const error_result = {
1022
+ _error: true,
1023
+ error: err,
1024
+ handler: obj.name,
1025
+ timestamp: Date.now()
1026
+ };
1027
+ proc_results[idx] = error_result;
1028
+
1029
+ // 全局错误处理器
1030
+ if (this.config.error_handler && typeof this.config.error_handler === 'function') {
1031
+ this.config.error_handler(err, { type: 'handler', handler: obj.name, ctx });
1032
+ }
1033
+ }
1034
+ };
1035
+
1036
+ /**
1037
+ * 执行事件(支持中间件和命名空间)
1038
+ * @param {string} key 事件关键字,支持space:key格式
1039
+ * @param {object} params 传递参数
1040
+ * @returns {Promise<object>} 返回包含results和cancel方法的对象
1041
+ */
1042
+ Eventer.prototype.run = async function (key, ...params) {
1043
+ return this._execute(key, { exec_mode: 'sequential' }, ...params);
1044
+ };
1045
+
1046
+ /**
1047
+ * 触发事件
1048
+ * @param {string} key 事件关键,支持space:key格式
1049
+ * @param {object} params 传递参数
1050
+ * @returns {Promise<object>} 返回包含results和cancel方法的对象
1051
+ */
1052
+ Eventer.prototype.emit = function (key, ...params) {
1053
+ // 内部调用 _execute 方法,但不等待结果
1054
+ try {
1055
+ let result = this._execute(key, { exec_mode: 'sequential' }, ...params);
1056
+ result.catch(e => this.log('error', '事件异步执行失败:', e));
1057
+ return {
1058
+ ...result,
1059
+ cancel: () => {
1060
+ try {
1061
+ return result.then(r => r && typeof r.cancel === 'function' && r.cancel());
1062
+ } catch (cancel_error) {
1063
+ this.log('error', `事件取消失败 [${key}]`, cancel_error);
1064
+ return Promise.resolve();
1065
+ }
1066
+ }
1067
+ };
1068
+ } catch (error) {
1069
+ this.log('error', `事件触发失败 [${key}]`, error);
1070
+ // 返回一个安全的默认结果
1071
+ return {
1072
+ results: [],
1073
+ cancelled: false,
1074
+ cancel: () => { },
1075
+ error: error
1076
+ };
1077
+ }
1078
+ };
1079
+
1080
+ /**
1081
+ * 异步触发事件,按顺序执行等待完成
1082
+ * @param {string} key 事件关键字,支持space:key格式
1083
+ * @param {...any} args 事件参数
1084
+ * @returns {Promise} - 事件触发结果
1085
+ */
1086
+ Eventer.prototype.emitWait = async function (key, ...args) {
1087
+ try {
1088
+ let result = await this._execute(key, { exec_mode: 'sequential' }, ...args);
1089
+ return result.results || [];
1090
+ } catch (error) {
1091
+ this.log('error', `等待事件触发失败 [${key}]`, error);
1092
+ return [];
1093
+ }
1094
+ };
1095
+
1096
+ /**
1097
+ * 异步触发事件,并发执行不等待
1098
+ * @param {string} key 事件关键字,支持space:key格式
1099
+ * @param {...any} args 事件参数
1100
+ * @returns {boolean} - 是否有监听者
1101
+ */
1102
+ Eventer.prototype.emitAsync = async function (key, ...args) {
1103
+ try {
1104
+ return this._execAsync(key, args);
1105
+ } catch (global_error) {
1106
+ this.log('error', `异步事件触发失败 [${key}]`, global_error);
1107
+ return false;
1108
+ }
1109
+ };
1110
+
1111
+ Eventer.prototype._execAsync = function (key, args) {
1112
+ // 解析命名空间
1113
+ let parsed = this._parseKey(key);
1114
+ let space = parsed.space;
1115
+ let event_key = parsed.key;
1116
+ let full_key = `${space}:${event_key}`;
1117
+
1118
+ // 获取事件列表
1119
+ let list = this._dict[space] && this._dict[space][event_key];
1120
+
1121
+ if (!list || list.length === 0) {
1122
+ return false;
1123
+ }
1124
+
1125
+ // 立即启动所有监听器,但不等待
1126
+ list.forEach(handler => {
1127
+ this._executeAsyncHandler(handler, args, full_key);
1128
+ });
1129
+
1130
+ return true;
1131
+ };
1132
+
1133
+ Eventer.prototype._executeAsyncHandler = function (handler, args, full_key) {
1134
+ try {
1135
+ // 使用 Promise.resolve 确保异步执行
1136
+ Promise.resolve(handler.func(...args))
1137
+ .catch(error => {
1138
+ this._handleAsyncError(error, full_key, args);
1139
+ });
1140
+ } catch (sync_error) {
1141
+ this._handleSyncError(sync_error, full_key, args);
1142
+ }
1143
+ };
1144
+
1145
+ Eventer.prototype._handleAsyncError = function (error, full_key, args) {
1146
+ // 错误处理 - 记录但不抛出
1147
+ this.log('error', `异步监听器错误 [${full_key}]:`, error);
1148
+ try {
1149
+ this.emit('async:error', error, full_key, args);
1150
+ } catch (error) {
1151
+ this.log('error', '错误事件触发失败 [async:error]', error);
1152
+ }
1153
+ };
1154
+
1155
+ Eventer.prototype._handleSyncError = function (sync_error, full_key, args) {
1156
+ // 同步错误处理
1157
+ this.log('error', `同步监听器错误 [${full_key}]:`, sync_error);
1158
+ try {
1159
+ this.emit('sync:error', sync_error, full_key, args);
1160
+ } catch (error) {
1161
+ this.log('error', '错误事件触发失败 [sync:error]', error);
1162
+ }
1163
+ };
1164
+
1165
+ /**
1166
+ * 异步触发事件,并发执行等待完成
1167
+ * @param {string} key 事件关键字,支持space:key格式
1168
+ * @param {...any} args 事件参数
1169
+ * @returns {Promise<Array>} - 所有监听器的执行结果
1170
+ */
1171
+ Eventer.prototype.emitAll = async function (key, ...args) {
1172
+ try {
1173
+ let result = await this._execute(key, { exec_mode: 'parallel' }, ...args);
1174
+ return result.results || [];
1175
+ } catch (error) {
1176
+ this.log('error', `并发事件触发失败 [${key}]`, error);
1177
+ return [];
1178
+ }
1179
+ };
1180
+
1181
+ /**
1182
+ * 异步触发事件,竞争执行
1183
+ * @param {string} key 事件关键字,支持space:key格式
1184
+ * @param {...any} args 事件参数
1185
+ * @returns {Promise} - 第一个完成的结果
1186
+ */
1187
+ Eventer.prototype.emitRace = async function (key, ...args) {
1188
+ try {
1189
+ let result = await this._execute(key, { exec_mode: 'race' }, ...args);
1190
+ return result.race || null;
1191
+ } catch (error) {
1192
+ this.log('error', `竞争事件触发失败 [${key}]`, error);
1193
+ return null;
1194
+ }
1195
+ };
1196
+
1197
+ /**
1198
+ * 异步触发事件,返回第一个有返回值的结果(不阻塞其他监听器)
1199
+ * @param {string} key 事件关键字,支持space:key格式
1200
+ * @param {...any} args 事件参数
1201
+ * @returns {Promise} - 第一个有返回值(非 undefined)的监听器结果
1202
+ * 所有监听器并行执行,返回第一个有返回值(非 undefined)的结果,返回 undefined 的监听器被跳过,其他监听器继续在后台执行不受影响
1203
+ */
1204
+ Eventer.prototype.emitFirst = async function (key, ...args) {
1205
+ try {
1206
+ let parsed = this._parseKey(key);
1207
+ let space = parsed.space;
1208
+ let event_key = parsed.key;
1209
+
1210
+ let list = this._dict[space] && this._dict[space][event_key];
1211
+ if (!list || list.length === 0) {
1212
+ return undefined;
1213
+ }
1214
+
1215
+ return await new Promise(resolve => {
1216
+ let settled = false;
1217
+ let pending = list.length;
1218
+
1219
+ for (let handler of list) {
1220
+ Promise.resolve(handler.func(...args)).then(result => {
1221
+ if (!settled && result !== undefined) {
1222
+ settled = true;
1223
+ resolve(result);
1224
+ }
1225
+ pending--;
1226
+ if (pending === 0 && !settled) {
1227
+ resolve(undefined);
1228
+ }
1229
+ }).catch(() => {
1230
+ pending--;
1231
+ if (pending === 0 && !settled) {
1232
+ resolve(undefined);
1233
+ }
1234
+ });
1235
+ }
1236
+ });
1237
+ } catch (error) {
1238
+ this.log('error', `首个结果事件触发失败 [${key}]`, error);
1239
+ return undefined;
1240
+ }
1241
+ };
1242
+
1243
+ /**
1244
+ * 异步触发事件,瀑布流执行
1245
+ * @param {string} key 事件关键字,支持space:key格式
1246
+ * @param {*} value 初始值
1247
+ * @param {...any} args 事件参数
1248
+ * @returns {Promise} - 最后一个事件监听者的结果
1249
+ */
1250
+ Eventer.prototype.emitWaterfall = async function (key, value, ...args) {
1251
+ try {
1252
+ let result = await this._execute(key, {
1253
+ exec_mode: 'waterfall',
1254
+ initial_value: value
1255
+ }, ...args);
1256
+ return result.waterfall || value;
1257
+ } catch (error) {
1258
+ this.log('error', `瀑布流事件触发失败 [${key}]`, error);
1259
+ return value;
1260
+ }
1261
+ };
1262
+
1263
+ /**
1264
+ * 确保命名空间在映射中
1265
+ * @private
1266
+ * @param {string} name 命名空间名称
1267
+ */
1268
+ Eventer.prototype._ensureNs = function (name) {
1269
+ if (!this._space[name]) {
1270
+ this._space[name] = true;
1271
+ }
1272
+ };
1273
+
1274
+ /**
1275
+ * 执行单个命名空间的事件处理函数
1276
+ * @private
1277
+ * @param {string} name 命名空间名称
1278
+ * @param {string} key 事件关键字
1279
+ * @param {Array} params 事件参数
1280
+ * @returns {object} 包含结果和需要移除的事件名称的对象
1281
+ */
1282
+ Eventer.prototype._execNsEvents = async function (name, key, params) {
1283
+ let list = this._dict[name][key];
1284
+ const name_results = [];
1285
+ const arr = []; // 存储需要移除的事件
1286
+
1287
+ // 执行事件处理函数
1288
+ for (let i = 0; i < list.length; i++) {
1289
+ try {
1290
+ let obj = list[i];
1291
+ // 执行事件处理函数
1292
+ let result = await obj.func.apply(obj, params);
1293
+ name_results.push(result);
1294
+
1295
+ // 处理执行次数限制
1296
+ if (obj.times >= 0) {
1297
+ obj.times--;
1298
+ if (obj.times <= 0) {
1299
+ arr.push(obj.name);
1300
+ }
1301
+ }
1302
+ } catch (e) {
1303
+ // 记录错误但不中断执行
1304
+ this.log('error', `事件执行失败 [${name}:${key}] - ${list[i].name}`, e);
1305
+ name_results.push({
1306
+ _error: true,
1307
+ error: e,
1308
+ handler: list[i].name
1309
+ });
1310
+ }
1311
+ }
1312
+
1313
+ return { name_results, arr };
1314
+ };
1315
+
1316
+ /**
1317
+ * 移除已执行完的事件
1318
+ * @private
1319
+ * @param {string} name 命名空间名称
1320
+ * @param {string} key 事件关键字
1321
+ * @param {Array} arr 需要移除的事件名称数组
1322
+ */
1323
+ Eventer.prototype.emitAllNamespaces = async function (key, ...params) {
1324
+ const results = {};
1325
+ // 确保遍历所有命名空间,包括动态创建的
1326
+ for (let name in this._dict) {
1327
+ // 确保命名空间在space映射中
1328
+ this._ensureNs(name);
1329
+
1330
+ // 检查该命名空间下是否存在该事件
1331
+ if (this._dict[name] && this._dict[name][key]) {
1332
+ const { name_results, arr } = await this._execNsEvents(name, key, params);
1333
+
1334
+ // 移除已执行完的事件
1335
+ this._removeEvents(name, key, arr);
1336
+
1337
+ results[name] = name_results;
1338
+ }
1339
+ }
1340
+ return results;
1341
+ };
1342
+
1343
+ /**
1344
+ * 删除单个事件监听器
1345
+ * @private
1346
+ * @param {Array} events 事件列表
1347
+ * @param {string | number} index_or_name 事件索引或名称
1348
+ * @returns {boolean} 删除成功返回true,否则返回false
1349
+ */
1350
+ Eventer.prototype._removeSingleEvent = function (events, index_or_name) {
1351
+ if (typeof (index_or_name) === 'number') {
1352
+ // 按索引删除
1353
+ if (index_or_name >= 0 && index_or_name < events.length) {
1354
+ events.splice(index_or_name, 1);
1355
+ return true;
1356
+ }
1357
+ } else {
1358
+ // 根据名称删除事件
1359
+ for (let j = events.length - 1; j >= 0; j--) {
1360
+ if (events[j].name === index_or_name) {
1361
+ events.splice(j, 1);
1362
+ return true;
1363
+ }
1364
+ }
1365
+ }
1366
+ return false;
1367
+ };
1368
+
1369
+ /**
1370
+ * 删除整个事件
1371
+ * @private
1372
+ * @param {string} space 命名空间
1373
+ * @param {string} event_key 事件键
1374
+ * @param {string} full_key 完整事件关键字
1375
+ * @returns {boolean} 删除成功返回true
1376
+ */
1377
+ Eventer.prototype._removeEntireEvent = function (space, event_key, full_key) {
1378
+ // 安全检查:确保命名空间和事件存在
1379
+ if (!this._dict[space] || !this._dict[space][event_key]) {
1380
+ return false;
1381
+ }
1382
+
1383
+ // 删除整个事件
1384
+ delete this._dict[space][event_key];
1385
+
1386
+ // 清理相关的事件链
1387
+ if (this._chain) {
1388
+ for (let chain_key in this._chain) {
1389
+ if (chain_key === full_key) {
1390
+ delete this._chain[chain_key];
1391
+ } else if (this._chain[chain_key] && Array.isArray(this._chain[chain_key]) &&
1392
+ this._chain[chain_key].includes(full_key)) {
1393
+ delete this._chain[chain_key];
1394
+ }
1395
+ }
1396
+ }
1397
+
1398
+ return true;
1399
+ };
1400
+
1401
+ /**
1402
+ * 自动清理空的事件列表和命名空间
1403
+ * @private
1404
+ * @param {string} space 命名空间
1405
+ * @param {string} key 事件关键字
1406
+ * @param {Array} events 事件列表
1407
+ * @param {string | number} index_or_name 事件索引或名称
1408
+ */
1409
+ Eventer.prototype._autoCleanEvents = function (space, key, events, index_or_name) {
1410
+ if (!this.config.auto_clean) return;
1411
+
1412
+ // 安全检查:确保命名空间存在
1413
+ if (!this._dict[space]) {
1414
+ return;
1415
+ }
1416
+
1417
+ // 清理空的事件列表
1418
+ if (index_or_name && events && events.length === 0) {
1419
+ // 安全检查:确保事件键存在
1420
+ if (this._dict[space][key]) {
1421
+ delete this._dict[space][key];
1422
+ }
1423
+ }
1424
+
1425
+ // 如果命名空间为空,则删除命名空间
1426
+ if (this._dict[space] && Object.keys(this._dict[space]).length === 0) {
1427
+ delete this._dict[space];
1428
+ if (this._space && this._space[space]) {
1429
+ delete this._space[space];
1430
+ }
1431
+ }
1432
+ };
1433
+
1434
+ /**
1435
+ * 删除事件
1436
+ * @param {string} key 事件关键字,支持space:key格式
1437
+ * @param {number | string} index_or_name 事件集索引或名称
1438
+ * @returns {boolean} 删除成功返回true,否则返回false
1439
+ */
1440
+ Eventer.prototype.off = function (key, index_or_name) {
1441
+ // 入参校验
1442
+ if (!key || typeof key !== 'string') {
1443
+ throw new Error('事件关键字必须是非空字符串');
1444
+ }
1445
+
1446
+ // 解析命名空间
1447
+ let parsed = this._parseKey(key);
1448
+ let space = parsed.space;
1449
+ let event_key = parsed.key;
1450
+ let full_key = `${space}:${event_key}`;
1451
+
1452
+ // 检查事件是否存在
1453
+ if (!this._dict[space] || !this._dict[space][event_key]) {
1454
+ return false;
1455
+ }
1456
+
1457
+ let events = this._dict[space][event_key];
1458
+ let removed = false;
1459
+
1460
+ if (index_or_name) {
1461
+ // 删除单个事件
1462
+ removed = this._removeSingleEvent(events, index_or_name);
1463
+ } else {
1464
+ // 删除整个事件
1465
+ removed = this._removeEntireEvent(space, event_key, full_key);
1466
+ }
1467
+
1468
+ // 自动清理
1469
+ if (removed) {
1470
+ this._autoCleanEvents(space, event_key, events, index_or_name);
1471
+ }
1472
+
1473
+ return removed;
1474
+ };
1475
+
1476
+ Eventer.prototype.add = Eventer.prototype.on;
1477
+ Eventer.prototype.del = Eventer.prototype.off;
1478
+
1479
+ /**
1480
+ * 删除命名空间中的所有事件
1481
+ * @param {string} name 命名空间
1482
+ * @returns {boolean} 删除成功返回true,否则返回false
1483
+ */
1484
+ Eventer.prototype.clearNamespace = function (name) {
1485
+ if (!name || !this._dict[name]) {
1486
+ return false;
1487
+ }
1488
+ delete this._dict[name];
1489
+ delete this._space[name];
1490
+ return true;
1491
+ };
1492
+
1493
+ /**
1494
+ * 获取事件列表
1495
+ * @param {string} key 事件关键字,如果为空则获取所有事件,支持space:key格式
1496
+ * @returns {Array | object} 返回事件列表或所有事件对象
1497
+ */
1498
+ Eventer.prototype.getEvents = function (key) {
1499
+ if (key) {
1500
+ // 解析命名空间
1501
+ const { space, key: event_key } = this._parseKey(key);
1502
+ return this._dict[space] &&
1503
+
1504
+ this._dict[space][event_key] ? [...this._dict[space][event_key]] : [];
1505
+ }
1506
+ // 返回深拷贝的所有事件
1507
+ const result = {};
1508
+ for (let name in this._dict) {
1509
+ result[name] = {};
1510
+ for (let key in this._dict[name]) {
1511
+ result[name][key] = [...this._dict[name][key]];
1512
+ }
1513
+ }
1514
+ return result;
1515
+ };
1516
+
1517
+ /**
1518
+ * 获取所有命名空间
1519
+ * @returns {Array} 返回所有命名空间数组
1520
+ */
1521
+ Eventer.prototype.getNamespace = function () {
1522
+ return Object.keys(this._space);
1523
+ };
1524
+
1525
+ /**
1526
+ * 清空所有事件和资源
1527
+ * @param {boolean} keep_space 是否保留命名空间定义,默认false
1528
+ * @returns {Eventer} 返回当前实例,支持链式调用
1529
+ */
1530
+ Eventer.prototype.clear = function (keep_space = false) {
1531
+ // 取消所有进行中的任务
1532
+ if (this._tasks) {
1533
+ this._tasks.forEach((tasks, key) => {
1534
+ tasks.forEach(task => {
1535
+ if (task && typeof task.cancel === 'function') {
1536
+ task.cancel();
1537
+ }
1538
+ });
1539
+ });
1540
+ this._tasks.clear();
1541
+ }
1542
+
1543
+ // 清空事件字典
1544
+ this._dict = {};
1545
+
1546
+ // 清空事件链
1547
+ this._chain = {};
1548
+
1549
+ // 清空暂停状态
1550
+ if (this._paused) {
1551
+ this._paused.clear();
1552
+ }
1553
+ if (this._paused_space) {
1554
+ this._paused_space.clear();
1555
+ }
1556
+ this._paused_global = false;
1557
+
1558
+ // 保留命名空间定义
1559
+ if (!keep_space) {
1560
+ this._space = {};
1561
+ // 重新初始化默认命名空间
1562
+ this._space[this.config.default_name] = true;
1563
+ }
1564
+
1565
+ return this;
1566
+ };
1567
+
1568
+ /**
1569
+ * 检查事件是否存在
1570
+ * @param {string} key 事件关键字,支持space:key格式
1571
+ * @param {string} name 事件名称(可选)
1572
+ * @returns {boolean} 事件存在返回true,否则返回false
1573
+ */
1574
+ Eventer.prototype.has = function (key, name) {
1575
+ // 解析命名空间
1576
+ let parsed = this._parseKey(key);
1577
+ let space = parsed.space;
1578
+ let event_key = parsed.key;
1579
+
1580
+ if (!this._dict[space] || !this._dict[space][event_key]) {
1581
+ return false;
1582
+ }
1583
+
1584
+ if (name) {
1585
+ let list = this._dict[space][event_key];
1586
+ for (let i = 0; i < list.length; i++) {
1587
+ if (list[i].name === name) {
1588
+ return true;
1589
+ }
1590
+ }
1591
+ return false;
1592
+ }
1593
+
1594
+ return true;
1595
+ };
1596
+
1597
+ /**
1598
+ * 获取事件数量
1599
+ * @param {string} key 事件关键字,如果为空则获取所有事件数量,支持space:key格式或space:*格式
1600
+ * @returns {number} 返回事件数量
1601
+ */
1602
+ Eventer.prototype.count = function (key) {
1603
+ if (key) {
1604
+ // 解析可能的命名空间模式
1605
+ if (key.endsWith(':*')) {
1606
+ // 统计命名空间下所有事件
1607
+ let space = key.split(':')[0];
1608
+ if (this._dict[space]) {
1609
+ let total = 0;
1610
+ for (let key in this._dict[space]) {
1611
+ total += this._dict[space][key].length;
1612
+ }
1613
+ return total;
1614
+ }
1615
+ return 0;
1616
+ }
1617
+
1618
+ // 解析具体事件
1619
+ const { space, key: event_key } = this._parseKey(key);
1620
+ return this._dict[space] &&
1621
+
1622
+ this._dict[space][event_key] ? this._dict[space][event_key].length : 0;
1623
+ }
1624
+
1625
+ // 统计所有事件
1626
+ let total = 0;
1627
+ for (let name in this._dict) {
1628
+ for (let key in this._dict[name]) {
1629
+ total += this._dict[name][key].length;
1630
+ }
1631
+ }
1632
+ return total;
1633
+ };
1634
+
1635
+ /**
1636
+ * 添加事件中间件
1637
+ * @param {string} type 中间件类型,'before' 或 'after'
1638
+ * @param {Function} middleware 中间件函数,接收ctx参数
1639
+ * @returns {Eventer} 返回当前实例,支持链式调用
1640
+ */
1641
+ Eventer.prototype.use = function (type, middleware) {
1642
+ if (type !== 'before' && type !== 'after') {
1643
+ throw new Error('中间件类型必须是 "before" 或 "after"');
1644
+ }
1645
+ if (typeof middleware !== 'function') {
1646
+ throw new Error('中间件必须是一个函数');
1647
+ }
1648
+
1649
+ if (!this._middleware[type]) {
1650
+ this._middleware[type] = [];
1651
+ }
1652
+ this._middleware[type].push(middleware);
1653
+ return this;
1654
+ };
1655
+
1656
+ /**
1657
+ * 添加事件链式触发关系
1658
+ * @param {string} from_event 源事件,支持space:key格式
1659
+ * @param {string | Array} to_events 目标事件,可以是单个事件或事件数组
1660
+ * @returns {Eventer} 返回当前实例,支持链式调用
1661
+ */
1662
+ Eventer.prototype.chain = function (from_event, to_events) {
1663
+ // 入参校验
1664
+ this._validateChainInput(from_event, to_events);
1665
+
1666
+ // 解析源事件
1667
+ let full_from_event = this._getFullEventKey(from_event);
1668
+
1669
+ // 初始化事件链
1670
+ this._initEventChain(full_from_event);
1671
+
1672
+ // 添加目标事件
1673
+ this._addTargetEvents(full_from_event, to_events);
1674
+
1675
+ return this;
1676
+ };
1677
+
1678
+ Eventer.prototype._validateChainInput = function (from_event, to_events) {
1679
+ if (!from_event || typeof from_event !== 'string') {
1680
+ throw new Error('源事件必须是非空字符串');
1681
+ }
1682
+ };
1683
+
1684
+ Eventer.prototype._getFullEventKey = function (event) {
1685
+ const { space, key } = this._parseKey(event);
1686
+ return `${space}:${key}`;
1687
+ };
1688
+
1689
+ Eventer.prototype._initEventChain = function (full_from_event) {
1690
+ if (!this._chain[full_from_event]) {
1691
+ this._chain[full_from_event] = [];
1692
+ }
1693
+ };
1694
+
1695
+ Eventer.prototype._addTargetEvents = function (full_from_event, to_events) {
1696
+ // 确保目标事件是数组
1697
+ let target_events = Array.isArray(to_events) ? to_events : [to_events];
1698
+
1699
+ for (let i = 0; i < target_events.length; i++) {
1700
+ this._addTargetEvent(full_from_event, target_events[i]);
1701
+ }
1702
+ };
1703
+
1704
+ Eventer.prototype._addTargetEvent = function (full_from_event, to_event) {
1705
+ if (typeof to_event !== 'string') {
1706
+ throw new Error('目标事件必须是非空字符串');
1707
+ }
1708
+
1709
+ // 解析目标事件
1710
+ let full_to_event = this._getFullEventKey(to_event);
1711
+
1712
+ // 避免重复添加
1713
+ if (!this._chain[full_from_event].includes(full_to_event)) {
1714
+ this._chain[full_from_event].push(full_to_event);
1715
+ }
1716
+ };
1717
+
1718
+ /**
1719
+ * 移除事件链式触发关系
1720
+ * @param {string} from_event 源事件,支持space:key格式
1721
+ * @param {string | Array} to_events 目标事件,可以是单个事件或事件数组(可选,不提供则移除所有关联)
1722
+ * @returns {Eventer} 返回当前实例,支持链式调用
1723
+ */
1724
+ Eventer.prototype.unchain = function (from_event, to_events) {
1725
+ // 入参校验
1726
+ if (!from_event || typeof from_event !== 'string') {
1727
+ throw new Error('源事件必须是非空字符串');
1728
+ }
1729
+
1730
+ // 解析源事件
1731
+ const { space: from_space, key: fromkey } = this._parseKey(from_event);
1732
+ let full_from_event = `${from_space}:${fromkey}`;
1733
+
1734
+ // 如果源事件不存在事件链,直接返回
1735
+ if (!this._chain[full_from_event]) {
1736
+ return this;
1737
+ }
1738
+
1739
+ if (to_events) {
1740
+ this._removeTargetEvents(full_from_event, to_events);
1741
+ } else {
1742
+ // 移除整个事件链
1743
+ delete this._chain[full_from_event];
1744
+ }
1745
+
1746
+ return this;
1747
+ };
1748
+
1749
+ Eventer.prototype._removeTargetEvents = function (full_from_event, to_events) {
1750
+ let target_events = Array.isArray(to_events) ? to_events : [to_events];
1751
+
1752
+ for (let i = 0; i < target_events.length; i++) {
1753
+ this._removeTargetEvent(full_from_event, target_events[i]);
1754
+ }
1755
+
1756
+ // 如果事件链为空,则删除整个事件链
1757
+ if (this._chain[full_from_event].length === 0) {
1758
+ delete this._chain[full_from_event];
1759
+ }
1760
+ };
1761
+
1762
+ Eventer.prototype._removeTargetEvent = function (full_from_event, to_event) {
1763
+ if (typeof to_event !== 'string') {
1764
+ throw new Error('目标事件必须是非空字符串');
1765
+ }
1766
+
1767
+ // 解析目标事件
1768
+ const { space: to_space, key: tokey } = this._parseKey(to_event);
1769
+ let full_to_event = `${to_space}:${tokey}`;
1770
+
1771
+ // 检查事件链是否存在
1772
+ if (!this._chain[full_from_event]) {
1773
+ this.log('warn', `事件链不存在: ${full_from_event} -> ${full_to_event}`);
1774
+ return;
1775
+ }
1776
+
1777
+ // 查找并删除事件链
1778
+ let index = this._chain[full_from_event].indexOf(full_to_event);
1779
+ if (index === -1) {
1780
+ this.log('warn', `事件链不存在: ${full_from_event} -> ${full_to_event}`);
1781
+ return;
1782
+ }
1783
+
1784
+ this._chain[full_from_event].splice(index, 1);
1785
+ };
1786
+
1787
+ /**
1788
+ * 获取事件链
1789
+ * @param {string} event 事件关键字,支持space:key格式
1790
+ * @returns {Array} 返回事件链数组
1791
+ */
1792
+ Eventer.prototype.getChains = function (event) {
1793
+ if (!event) {
1794
+ return Object.keys(this._chain);
1795
+ }
1796
+
1797
+ // 解析事件
1798
+ const { space, key } = this._parseKey(event);
1799
+ let full_event = `${space}:${key}`;
1800
+
1801
+ return this._chain[full_event] ? [...this._chain[full_event]] : [];
1802
+ };
1803
+
1804
+ /**
1805
+ * 触发下一级事件链事件
1806
+ * @private
1807
+ * @param {string} current_event 当前触发的事件
1808
+ * @param {Array} params 传递的参数
1809
+ * @returns {Promise<void>}
1810
+ */
1811
+ /**
1812
+ * 并行执行事件(提高性能)
1813
+ * @param {string} key 事件关键字,支持space:key格式
1814
+ * @param {object} params 传递参数
1815
+ * @returns {Promise<object>} 返回包含results和cancel方法的对象
1816
+ */
1817
+ Eventer.prototype.runParallel = async function (key, ...params) {
1818
+ let result = await this._execute(key, {
1819
+ exec_mode: 'parallel',
1820
+ options: params.options
1821
+ }, ...params);
1822
+ return {
1823
+ results: result.results,
1824
+ cancelled: result.cancelled,
1825
+ cancel: result.cancel
1826
+ };
1827
+ };
1828
+
1829
+ /**
1830
+ * 并行触发事件
1831
+ * @param {string} key 事件关键字,支持space:key格式
1832
+ * @param {object} params 传递参数
1833
+ * @returns {Promise<object>} 返回包含results和cancel方法的对象
1834
+ */
1835
+ Eventer.prototype.emitParallel = function (key, ...params) {
1836
+ // 内部调用 _execute 方法,但不等待结果
1837
+ let result = this._execute(key, {
1838
+ exec_mode: 'parallel',
1839
+ options: params.options
1840
+ }, ...params);
1841
+ result.catch(e => this.log('error', '事件并行执行失败:', e));
1842
+ return {
1843
+ ...result,
1844
+ cancel: () => result.then(r => r && typeof r.cancel === 'function' && r.cancel())
1845
+ };
1846
+ };
1847
+
1848
+ /**
1849
+ * 防止内存泄漏警告
1850
+ * @param {number} max_listen 最大监听器数量
1851
+ * @returns {Eventer} 返回当前实例,支持链式调用
1852
+ */
1853
+ Eventer.prototype.setMaxListeners = function (max_listen) {
1854
+ if (typeof max_listen !== 'number' || max_listen < 0) {
1855
+ throw new Error('最大监听器数量必须是一个非负数');
1856
+ }
1857
+ this._max_listeners = max_listen;
1858
+ return this;
1859
+ };
1860
+
1861
+ /**
1862
+ * 批量添加事件
1863
+ * @param {object} events_map 事件映射对象 { key: [func1, func2...] 或 key: {func, options} }
1864
+ * @returns {Eventer} 返回当前实例,支持链式调用
1865
+ */
1866
+ Eventer.prototype.onMany = function (events_map) {
1867
+ if (typeof events_map !== 'object' || events_map === null) {
1868
+ throw new Error('事件对象必须是一个非空对象');
1869
+ }
1870
+
1871
+ for (let event_name in events_map) {
1872
+ if (Object.prototype.hasOwnProperty.call(events_map, event_name)) {
1873
+ this.on(event_name, events_map[event_name]);
1874
+ }
1875
+ }
1876
+ return this;
1877
+ };
1878
+
1879
+ // 私有方法
1880
+
1881
+ /**
1882
+ * 解析事件键,提取命名空间和事件键
1883
+ * @param {string} key 事件关键字
1884
+ * @returns {object} 包含space和key的对象
1885
+ * @private
1886
+ */
1887
+ Eventer.prototype._parseKey = function (key) {
1888
+ let parts = key.split(':');
1889
+ if (parts.length === 1) {
1890
+ // 没有命名空间,使用默认命名空间
1891
+ return {
1892
+ space: this.config.default_name,
1893
+ key: key
1894
+ };
1895
+ } else if (parts.length === 2) {
1896
+ // 有命名空间
1897
+ return {
1898
+ space: parts[0],
1899
+ key: parts[1]
1900
+ };
1901
+ } else {
1902
+ // 多个冒号,将第一个作为命名空间,其余作为事件键
1903
+ return {
1904
+ space: parts[0],
1905
+ key: parts.slice(1).join(':')
1906
+ };
1907
+ }
1908
+ };
1909
+
1910
+ /**
1911
+ * 按优先级对事件列表进行排序
1912
+ * @param {Array} events 事件列表
1913
+ * @private
1914
+ */
1915
+ Eventer.prototype._sort = function (events) {
1916
+ events.sort((a, b) => a.priority - b.priority);
1917
+ };
1918
+
1919
+ /**
1920
+ * 运行中间件
1921
+ * @param {string} type 中间件类型:'before' 或 'after'
1922
+ * @param {object} ctx 上下文对象
1923
+ * @private
1924
+ */
1925
+ Eventer.prototype._runMiddleware = async function (type, ctx) {
1926
+ if (!this._middleware || !this._middleware[type] || this._middleware[type].length === 0) return;
1927
+
1928
+ const mwList = this._middleware[type];
1929
+ for (let i = 0; i < mwList.length; i++) {
1930
+ await this._execMiddleware(mwList[i], type, ctx, i);
1931
+ // 如果上下文被取消,则停止执行
1932
+ if (ctx.cancelled) break;
1933
+ }
1934
+ };
1935
+
1936
+ Eventer.prototype._execMiddleware = async function (middleware, type, ctx, idx) {
1937
+ if (middleware && typeof middleware[type] === 'function') {
1938
+ try {
1939
+ await middleware[type].call(this, ctx);
1940
+ } catch (middleware_error) {
1941
+ this._handleMwareError(middleware_error, type, idx, ctx);
1942
+ }
1943
+ }
1944
+ };
1945
+
1946
+ Eventer.prototype._handleMwareError = function (middleware_error, type, index, ctx) {
1947
+ this.log('error', `中间件执行失败 [${type}] - 索引:${index}`, middleware_error);
1948
+
1949
+ // 全局错误处理器
1950
+ if (this.config.error_handler && typeof this.config.error_handler === 'function') {
1951
+ try {
1952
+ this.config.error_handler(middleware_error, {
1953
+ type: 'middleware',
1954
+ stage: type,
1955
+ index: index,
1956
+ ctx
1957
+ });
1958
+ } catch (handler_error) {
1959
+ this.log('error', '全局错误处理器执行失败', handler_error);
1960
+ }
1961
+ }
1962
+ };
1963
+
1964
+ /**
1965
+ * 触发下一级事件链
1966
+ * @param {string} current_event 当前事件键
1967
+ * @param {Array} params 参数数组
1968
+ * @private
1969
+ */
1970
+ Eventer.prototype._triggerChain = async function (current_event, params) {
1971
+ // 获取当前事件的下级事件列表
1972
+ var next_events = this._chain[current_event];
1973
+ if (!next_events || next_events.length === 0) return;
1974
+
1975
+ // 遍历并触发所有下级事件
1976
+ for (var i = 0; i < next_events.length; i++) {
1977
+ await this._triggerChainEvent(next_events[i], current_event, params);
1978
+ }
1979
+ };
1980
+
1981
+ Eventer.prototype._triggerChainEvent = async function (key, current_event, params) {
1982
+ // 避免重复执行当前事件
1983
+ if (key === current_event) return;
1984
+
1985
+ // 创建下级事件的上下文
1986
+ var ctx = this._createChainCtx(key, current_event, params);
1987
+
1988
+ // 执行前置中间件
1989
+ await this._runChainMware('before', ctx);
1990
+ if (ctx.cancelled) return;
1991
+
1992
+ // 触发下级事件
1993
+ await this._executeChainEvent(key, params, ctx);
1994
+
1995
+ // 执行后置中间件
1996
+ await this._runChainMware('after', ctx);
1997
+
1998
+ // 递归触发下级事件的下级事件
1999
+ if (!ctx.cancelled) {
2000
+ await this._triggerChain(ctx.full_event, params);
2001
+ }
2002
+ };
2003
+
2004
+ Eventer.prototype._createChainCtx = function (key, current_event, params) {
2005
+ var { space, key: inner_key } = this._parseKey(key);
2006
+ var full_key = `${space}:${inner_key}`;
2007
+
2008
+ return {
2009
+ space,
2010
+ event: inner_key,
2011
+ full_event: full_key,
2012
+ params,
2013
+ parent_event: current_event,
2014
+ start_time: Date.now(),
2015
+ executed: 0,
2016
+ error_count: 0,
2017
+ cancelled: false,
2018
+ /**
2019
+ * 取消事件执行
2020
+ */
2021
+ cancel: () => { this.cancelled = true; }
2022
+ };
2023
+ };
2024
+
2025
+ Eventer.prototype._runChainMware = async function (type, ctx) {
2026
+ try {
2027
+ if (type === 'after') {
2028
+ ctx.end_time = Date.now();
2029
+ ctx.duration = ctx.end_time - ctx.start_time;
2030
+ }
2031
+ await this._runMiddleware(type, ctx);
2032
+ } catch (error) {
2033
+ this.log('error', `下级事件${type}中间件执行失败 [${ctx.full_event}]`, error);
2034
+ }
2035
+ };
2036
+
2037
+ Eventer.prototype._executeChainEvent = async function (key, params, ctx) {
2038
+ try {
2039
+ await this.run(key, ...params);
2040
+ } catch (event_error) {
2041
+ this.log('error', `下级事件执行失败 [${ctx.full_event}]`, event_error);
2042
+ }
2043
+ };
2044
+
2045
+ /**
2046
+ * 节流函数
2047
+ * @param {Function} func 要节流的函数
2048
+ * @param {number} limit 节流时间(毫秒)
2049
+ * @returns {Function} 节流后的函数
2050
+ * @private
2051
+ */
2052
+ Eventer.prototype._throttle = function (func, limit) {
2053
+ let last_func;
2054
+ let last_time = 0;
2055
+ return function () {
2056
+ let ctx = this;
2057
+ let args = arguments;
2058
+ if (!last_time) {
2059
+ func.apply(ctx, args);
2060
+ last_time = Date.now();
2061
+ } else {
2062
+ clearTimeout(last_func);
2063
+ last_func = setTimeout(() => {
2064
+ if ((Date.now() - last_time) >= limit) {
2065
+ func.apply(ctx, args);
2066
+ last_time = Date.now();
2067
+ }
2068
+ }, limit - (Date.now() - last_time));
2069
+ }
2070
+ };
2071
+ };
2072
+
2073
+ /**
2074
+ * 防抖函数
2075
+ * @param {Function} func 要防抖的函数
2076
+ * @param {number} wait 防抖时间(毫秒)
2077
+ * @returns {Function} 防抖后的函数
2078
+ * @private
2079
+ */
2080
+ Eventer.prototype._debounce = function (func, wait) {
2081
+ let timeout;
2082
+ return function () {
2083
+ let ctx = this;
2084
+ let args = arguments;
2085
+ clearTimeout(timeout);
2086
+ timeout = setTimeout(() => {
2087
+ func.apply(ctx, args);
2088
+ }, wait);
2089
+ };
2090
+ };
2091
+
2092
+
2093
+ /**
2094
+ * 暂停事件执行
2095
+ * @param {string} key 事件关键字或命名空间,支持space:key格式,为空表示全局暂停
2096
+ * @returns {boolean} 是否成功暂停
2097
+ */
2098
+ Eventer.prototype.pause = function (key = '') {
2099
+ if (!this.config.pause_enabled) {
2100
+ this.log('warn', '暂停功能未启用');
2101
+ return false;
2102
+ }
2103
+
2104
+ if (!key) {
2105
+ return this._pauseGlobal();
2106
+ }
2107
+
2108
+ // 解析关键字
2109
+ let parsed = this._parseKey(key);
2110
+ let space = parsed.space;
2111
+ let event_key = parsed.key;
2112
+ let full_key = `${space}:${event_key}`;
2113
+
2114
+ if (key) {
2115
+ return this._pauseEvent(full_key);
2116
+ } else {
2117
+ return this._pauseNamespace(space);
2118
+ }
2119
+ };
2120
+
2121
+ Eventer.prototype._pauseGlobal = function () {
2122
+ if (this._paused_global) {
2123
+ this.log('warn', '事件总线已处于全局暂停状态');
2124
+ return false;
2125
+ }
2126
+ this._paused_global = true;
2127
+ this.log('info', '事件总线已全局暂停');
2128
+ return true;
2129
+ };
2130
+
2131
+ Eventer.prototype._pauseEvent = function (full_key) {
2132
+ if (this._paused.has(full_key)) {
2133
+ this.log('warn', `事件 '${full_key}' 已处于暂停状态`);
2134
+ return false;
2135
+ }
2136
+ this._paused.add(full_key);
2137
+ this.log('info', `事件 '${full_key}' 已暂停`);
2138
+ return true;
2139
+ };
2140
+
2141
+ Eventer.prototype._pauseNamespace = function (space) {
2142
+ if (this._paused_space.has(space)) {
2143
+ this.log('warn', `命名空间 '${space}' 已处于暂停状态`);
2144
+ return false;
2145
+ }
2146
+ this._paused_space.add(space);
2147
+ this.log('info', `命名空间 '${space}' 已暂停`);
2148
+ return true;
2149
+ };
2150
+
2151
+ /**
2152
+ * 恢复事件执行
2153
+ * @param {string} key 事件关键字或命名空间,支持space:key格式,为空表示恢复全局暂停
2154
+ * @returns {boolean} 是否成功恢复
2155
+ */
2156
+ Eventer.prototype.resume = function (key = '') {
2157
+ if (!this.config.pause_enabled) {
2158
+ this.log('warn', '暂停功能未启用');
2159
+ return false;
2160
+ }
2161
+
2162
+ if (!key) {
2163
+ return this._resumeGlobal();
2164
+ }
2165
+
2166
+ // 解析关键字
2167
+ let parsed = this._parseKey(key);
2168
+ let space = parsed.space;
2169
+ let event_key = parsed.key;
2170
+ let full_key = `${space}:${event_key}`;
2171
+
2172
+ if (key) {
2173
+ return this._resumeEvent(full_key);
2174
+ } else {
2175
+ return this._resumeNamespace(space);
2176
+ }
2177
+ };
2178
+
2179
+ Eventer.prototype._resumeGlobal = function () {
2180
+ if (!this._paused_global) {
2181
+ this.log('warn', '事件总线未处于全局暂停状态');
2182
+ return false;
2183
+ }
2184
+ this._paused_global = false;
2185
+ this.log('info', '事件总线已恢复运行');
2186
+ return true;
2187
+ };
2188
+
2189
+ Eventer.prototype._resumeEvent = function (full_key) {
2190
+ if (!this._paused.has(full_key)) {
2191
+ this.log('warn', `事件 '${full_key}' 未处于暂停状态`);
2192
+ return false;
2193
+ }
2194
+ this._paused.delete(full_key);
2195
+ this.log('info', `事件 '${full_key}' 已恢复`);
2196
+ return true;
2197
+ };
2198
+
2199
+ Eventer.prototype._resumeNamespace = function (space) {
2200
+ if (!this._paused_space.has(space)) {
2201
+ this.log('warn', `命名空间 '${space}' 未处于暂停状态`);
2202
+ return false;
2203
+ }
2204
+ this._paused_space.delete(space);
2205
+ this.log('info', `命名空间 '${space}' 已恢复`);
2206
+ return true;
2207
+ };
2208
+
2209
+ /**
2210
+ * 检查事件是否被暂停
2211
+ * @param {string} key 事件关键字,支持space:key格式
2212
+ * @returns {boolean} 是否被暂停
2213
+ */
2214
+ Eventer.prototype.isPaused = function (key) {
2215
+ if (!this.config.pause_enabled) {
2216
+ return false;
2217
+ }
2218
+
2219
+ // 全局暂停检查
2220
+ if (this._paused_global) {
2221
+ return true;
2222
+ }
2223
+
2224
+ // 解析关键字
2225
+ let parsed = this._parseKey(key);
2226
+ let space = parsed.space;
2227
+ let event_key = parsed.key;
2228
+ let full_key = `${space}:${event_key}`;
2229
+
2230
+ // 命名空间暂停检查
2231
+ if (this._paused_space.has(space)) {
2232
+ return true;
2233
+ }
2234
+
2235
+ // 单个事件暂停检查
2236
+ if (this._paused.has(full_key)) {
2237
+ return true;
2238
+ }
2239
+
2240
+ return false;
2241
+ };
2242
+
2243
+ /**
2244
+ * 获取所有暂停的事件和命名空间
2245
+ * @returns {object} 暂停状态信息
2246
+ */
2247
+ Eventer.prototype.getPausedStatus = function () {
2248
+ return {
2249
+ global_paused: this._paused_global,
2250
+ paused_events: Array.from(this._paused),
2251
+ paused_spaces: Array.from(this._paused_space)
2252
+ };
2253
+ };
2254
+
2255
+ /**
2256
+ * 清除所有暂停状态
2257
+ * @returns {boolean} 是否成功清除
2258
+ */
2259
+ Eventer.prototype.clearPaused = function () {
2260
+ if (!this.config.pause_enabled) {
2261
+ this.log('warn', '暂停功能未启用');
2262
+ return false;
2263
+ }
2264
+
2265
+ let cleared = false;
2266
+
2267
+ if (this._paused_global) {
2268
+ this._paused_global = false;
2269
+ cleared = true;
2270
+ }
2271
+
2272
+ if (this._paused.size > 0) {
2273
+ this._paused.clear();
2274
+ cleared = true;
2275
+ }
2276
+
2277
+ if (this._paused_space.size > 0) {
2278
+ this._paused_space.clear();
2279
+ cleared = true;
2280
+ }
2281
+
2282
+ if (cleared) {
2283
+ this.log('info', '所有暂停状态已清除');
2284
+ }
2285
+
2286
+ return cleared;
2287
+ };
2288
+
2289
+ let eventer = new Eventer();
2290
+
2291
+ module.exports = {
2292
+ Eventer,
2293
+ eventer
2294
+ };