fastevent 1.1.3 → 2.0.1

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.
Files changed (80) hide show
  1. package/dist/devTools.js +2 -2
  2. package/dist/devTools.js.map +1 -1
  3. package/dist/devTools.mjs +2 -2
  4. package/dist/devTools.mjs.map +1 -1
  5. package/dist/index.d.mts +304 -53
  6. package/dist/index.d.ts +304 -53
  7. package/dist/index.js +1 -1
  8. package/dist/index.js.map +1 -1
  9. package/dist/index.mjs +1 -1
  10. package/dist/index.mjs.map +1 -1
  11. package/package.json +64 -50
  12. package/readme.md +517 -50
  13. package/.changeset/README.md +0 -8
  14. package/.changeset/config.json +0 -11
  15. package/.github/workflows/publish.yaml +0 -50
  16. package/.prettierrc.js +0 -20
  17. package/.vscode/launch.json +0 -20
  18. package/.vscode/settings.json +0 -18
  19. package/CHANGELOG.md +0 -60
  20. package/LICENSE +0 -21
  21. package/bench.png +0 -0
  22. package/dist/devTools.d.mts +0 -543
  23. package/dist/devTools.d.ts +0 -543
  24. package/example/README.md +0 -54
  25. package/example/eslint.config.js +0 -28
  26. package/example/index.html +0 -13
  27. package/example/package.json +0 -29
  28. package/example/pnpm-lock.yaml +0 -2047
  29. package/example/public/vite.svg +0 -1
  30. package/example/src/App.css +0 -42
  31. package/example/src/App.tsx +0 -60
  32. package/example/src/assets/react.svg +0 -1
  33. package/example/src/index.css +0 -68
  34. package/example/src/main.tsx +0 -10
  35. package/example/src/myEvent.ts +0 -32
  36. package/example/src/vite-env.d.ts +0 -1
  37. package/example/tsconfig.app.json +0 -26
  38. package/example/tsconfig.json +0 -7
  39. package/example/tsconfig.node.json +0 -24
  40. package/example/vite.config.ts +0 -7
  41. package/packages/native/index.ts +0 -1
  42. package/packages/turbo/.zig-cache/h/271c82d991949fd7788fd5451f0ca834.txt +0 -0
  43. package/packages/turbo/.zig-cache/h/timestamp +0 -0
  44. package/packages/turbo/.zig-cache/o/ebd7ddab8ffe003267120d598aecce68/dependencies.zig +0 -2
  45. package/packages/turbo/.zig-cache/z/c8114b040daa461a9e2eabd0357554a4 +0 -0
  46. package/packages/turbo/build.zig +0 -60
  47. package/packages/turbo/examples/basic.zig +0 -107
  48. package/packages/turbo/src/event.zig +0 -251
  49. package/packages/turbo/src/index.zig +0 -70
  50. package/packages/turbo/src/scope.zig +0 -104
  51. package/packages/turbo/src/types.zig +0 -88
  52. package/packages/turbo/src/utils.zig +0 -171
  53. package/readme_cn.md +0 -491
  54. package/src/__benchmarks__/index.ts +0 -3
  55. package/src/__benchmarks__/multi-level.ts +0 -40
  56. package/src/__benchmarks__/sample.ts +0 -40
  57. package/src/__benchmarks__/wildcard.ts +0 -41
  58. package/src/__tests__/emit.test.ts +0 -106
  59. package/src/__tests__/emitAsync.test.ts +0 -64
  60. package/src/__tests__/isPathMatched.test.ts +0 -205
  61. package/src/__tests__/many.test.ts +0 -22
  62. package/src/__tests__/meta.test.ts +0 -28
  63. package/src/__tests__/off.test.ts +0 -214
  64. package/src/__tests__/onany.test.ts +0 -212
  65. package/src/__tests__/once.test.ts +0 -70
  66. package/src/__tests__/retain.test.ts +0 -66
  67. package/src/__tests__/scope.test.ts +0 -110
  68. package/src/__tests__/types.test.ts +0 -145
  69. package/src/__tests__/waitFor.test.ts +0 -116
  70. package/src/__tests__/wildcard.test.ts +0 -185
  71. package/src/devTools.ts +0 -166
  72. package/src/event.ts +0 -741
  73. package/src/index.ts +0 -3
  74. package/src/scope.ts +0 -130
  75. package/src/types.ts +0 -66
  76. package/src/utils/WeakObjectMap.ts +0 -64
  77. package/src/utils/isPathMatched.ts +0 -40
  78. package/src/utils/removeItem.ts +0 -16
  79. package/tsconfig.json +0 -104
  80. package/tsup.config.ts +0 -30
package/src/event.ts DELETED
@@ -1,741 +0,0 @@
1
- import { FastEventScope } from './scope';
2
- import {
3
- FastEventListener,
4
- FastEventOptions,
5
- FastEvents,
6
- FastListeners,
7
- FastListenerNode,
8
- FastEventSubscriber,
9
- ScopeEvents,
10
- FastEventListenOptions,
11
- FastEventMessage
12
- } from './types';
13
- import { isPathMatched } from './utils/isPathMatched';
14
- import { removeItem } from './utils/removeItem';
15
-
16
- /**
17
- * FastEvent 事件发射器类
18
- *
19
- * @template Events - 事件类型定义,继承自FastEvents接口
20
- * @template Meta - 事件元数据类型,默认为任意键值对对象
21
- * @template Types - 事件类型的键名类型,默认为Events的键名类型
22
- */
23
- export class FastEvent<
24
- Events extends FastEvents = FastEvents,
25
- Meta extends Record<string, any> = Record<string, any>,
26
- Context = any,
27
- Types extends keyof Events = keyof Events
28
- > {
29
- /** 事件监听器树结构,存储所有注册的事件监听器 */
30
- public listeners: FastListeners = { __listeners: [] } as unknown as FastListeners
31
-
32
- /** 事件发射器的配置选项 */
33
- private _options: FastEventOptions
34
-
35
- /** 事件名称的分隔符,默认为'/' */
36
- private _delimiter: string = '/'
37
-
38
- /** 事件监听器执行时的上下文对象 */
39
- private _context: Context
40
-
41
- /** 保留的事件消息映射,用于新订阅者 */
42
- retainedMessages: Map<string, any> = new Map<string, any>()
43
-
44
- /** 当前注册的监听器总数 */
45
- listenerCount: number = 0
46
- /**
47
- * 创建FastEvent实例
48
- * @param options - 事件发射器的配置选项
49
- *
50
- * 默认配置:
51
- * - debug: false - 是否启用调试模式
52
- * - id: 随机字符串 - 实例唯一标识符
53
- * - delimiter: '/' - 事件名称分隔符
54
- * - context: null - 监听器执行上下文
55
- * - ignoreErrors: true - 是否忽略监听器执行错误
56
- */
57
- constructor(options?: FastEventOptions<Meta>) {
58
- this._options = Object.assign({
59
- debug: false,
60
- id: Math.random().toString(36).substring(2),
61
- delimiter: '/',
62
- context: null,
63
- ignoreErrors: true
64
- }, options)
65
- this._delimiter = this._options.delimiter!
66
- this._context = this._options.context || this
67
- this._enableDevTools()
68
- }
69
-
70
- /** 获取事件发射器的配置选项 */
71
- get options() { return this._options }
72
-
73
- /** 获取事件发射器的唯一标识符 */
74
- get id() { return this._options.id! }
75
- private _addListener(parts: string[], listener: FastEventListener<any, any>, options: Required<FastEventListenOptions>): FastListenerNode | undefined {
76
- const { count, prepend } = options
77
- return this._forEachNodes(parts, (node) => {
78
- const newListener = count > 0 ? [listener, count] : listener as any
79
- if (prepend) {
80
- node.__listeners.splice(0, 0, newListener)
81
- } else {
82
- node.__listeners.push(newListener)
83
- }
84
- if (typeof (this._options.onAddListener) === 'function') {
85
- this.listenerCount++
86
- this._options.onAddListener(parts, listener)
87
- }
88
- })
89
- }
90
- private _enableDevTools() {
91
- if (this.options.debug) {
92
- // @ts-ignore
93
- globalThis.__FLEXEVENT_DEVTOOLS__.add(this)
94
- }
95
- }
96
- /**
97
- *
98
- * 根据parts路径遍历侦听器树,并在最后的节点上执行回调函数
99
- *
100
- * @param parts
101
- * @param callback
102
- * @returns
103
- */
104
- private _forEachNodes(parts: string[], callback: (node: FastListenerNode, parent: FastListenerNode) => void): FastListenerNode | undefined {
105
- if (parts.length === 0) return
106
- let current = this.listeners
107
- for (let i = 0; i < parts.length; i++) {
108
- const part = parts[i]
109
- if (!(part in current)) {
110
- current[part] = {
111
- __listeners: []
112
- } as unknown as FastListeners
113
- }
114
- if (i === parts.length - 1) {
115
- const node = current[part]
116
- callback(node, current)
117
- return node
118
- } else {
119
- current = current[part]
120
- }
121
- }
122
- return undefined
123
- }
124
-
125
-
126
- /**
127
- * 从监听器节点中移除指定的事件监听器
128
- * @private
129
- * @param node - 监听器节点
130
- * @param listener - 需要移除的事件监听器
131
- * @description 遍历节点的监听器列表,移除所有匹配的监听器。支持移除普通函数和数组形式的监听器
132
- */
133
- private _removeListener(node: FastListenerNode, path: string[], listener: FastEventListener<any, any, any>): void {
134
- if (!listener) return
135
- removeItem(node.__listeners, (item: any) => {
136
- item = Array.isArray(item) ? item[0] : item
137
- const isRemove = item === listener
138
- if (isRemove && typeof (this._options.onRemoveListener) === 'function') {
139
- this.listenerCount--
140
- this._options.onRemoveListener(path, listener)
141
- }
142
- return isRemove
143
- })
144
- }
145
- /**
146
- * 注册事件监听器
147
- * @param type - 事件类型,支持以下格式:
148
- * - 普通字符串:'user/login'
149
- * - 通配符:'user/*'(匹配单层)或'user/**'(匹配多层)
150
- * - 全局监听:'**'(监听所有事件)
151
- * @param listener - 事件监听器函数
152
- * @param options - 监听器配置选项:
153
- * - count: 触发次数限制,0表示无限制
154
- * - prepend: 是否将监听器添加到监听器队列开头
155
- * @returns 返回订阅者对象,包含off方法用于取消监听
156
- *
157
- * @example
158
- * ```ts
159
- * // 监听特定事件
160
- * emitter.on('user/login', (data) => console.log(data));
161
- *
162
- * // 使用通配符
163
- * emitter.on('user/*', (data) => console.log(data));
164
- *
165
- * // 限制触发次数
166
- * emitter.on('event', handler, { count: 3 });
167
- * ```
168
- */
169
- public on<T extends string>(type: T, listener: FastEventListener<T, Events[T], Meta, Context>, options?: FastEventListenOptions): FastEventSubscriber
170
- public on<T extends Types = Types>(type: T, listener: FastEventListener<Types, Events[T], Meta, Context>, options?: FastEventListenOptions): FastEventSubscriber
171
- public on<P = any>(type: '**', listener: FastEventListener<Types, P, Meta, Context>): FastEventSubscriber
172
- public on(): FastEventSubscriber {
173
- const type = arguments[0] as string
174
- const listener = arguments[1] as FastEventListener
175
- const options = Object.assign({
176
- count: 0,
177
- prepend: false
178
- }, arguments[2]) as Required<FastEventListenOptions>
179
-
180
- if (type.length === 0) throw new Error('event type cannot be empty')
181
-
182
- if (type === '**') {
183
- return this.onAny(listener)
184
- }
185
-
186
- const parts = type.split(this._delimiter);
187
- const node = this._addListener(parts, listener, options)
188
-
189
- // Retain不支持通配符
190
- if (node && !type.includes('*')) this._emitForLastEvent(type)
191
-
192
- return {
193
- off: () => node && this._removeListener(node, parts, listener)
194
- }
195
- }
196
-
197
-
198
- /**
199
- * 注册一次性事件监听器
200
- * @param type - 事件类型,支持与on方法相同的格式:
201
- * - 普通字符串:'user/login'
202
- * - 通配符:'user/*'(匹配单层)或'user/**'(匹配多层)
203
- * @param listener - 事件监听器函数
204
- * @returns 返回订阅者对象,包含off方法用于取消监听
205
- *
206
- * @description
207
- * 监听器只会在事件首次触发时被调用一次,之后会自动解除注册。
208
- * 这是on方法的特例,相当于设置options.count = 1。
209
- * 如果事件有保留消息,新注册的监听器会立即收到最近一次的保留消息并解除注册。
210
- *
211
- * @example
212
- * ```ts
213
- * // 只监听一次登录事件
214
- * emitter.once('user/login', (data) => {
215
- * console.log('用户登录:', data);
216
- * });
217
- * ```
218
- */
219
- public once<T extends Types = Types>(type: T, listener: FastEventListener<T, Events[T], Meta, Context>): FastEventSubscriber
220
- public once<T extends string>(type: T, listener: FastEventListener<T, Events[T], Meta, Context>): FastEventSubscriber
221
- public once(): FastEventSubscriber {
222
- return this.on(arguments[0], arguments[1], { count: 1 })
223
- }
224
-
225
- /**
226
- * 注册一个监听器,用于监听所有事件
227
- * @param listener 事件监听器函数,可以接收任意类型的事件数据
228
- * @returns {FastEventSubscriber} 返回一个订阅者对象,包含 off 方法用于取消监听
229
- * @example
230
- * ```ts
231
- * const subscriber = emitter.onAny((eventName, data) => {
232
- * console.log(eventName, data);
233
- * });
234
- *
235
- * // 取消监听
236
- * subscriber.off();
237
- * ```
238
- */
239
- onAny<P = any>(listener: FastEventListener<string, P, Meta, Context>, options?: Pick<FastEventListenOptions, 'prepend'>): FastEventSubscriber {
240
- const listeners = this.listeners.__listeners
241
- if (options && options.prepend) {
242
- listeners.splice(0, 0, listener)
243
- } else {
244
- listeners.push(listener)
245
- }
246
- return {
247
- off: () => this._removeListener(this.listeners, [], listener)
248
- }
249
- }
250
-
251
- off(listener: FastEventListener<any, any, any>): void
252
- off(type: string, listener: FastEventListener<any, any, any>): void
253
- off(type: Types, listener: FastEventListener<any, any, any>): void
254
- off(type: string): void
255
- off(type: Types): void
256
- off() {
257
- const args = arguments
258
- const type = typeof (args[0]) === 'function' ? undefined : args[0]
259
- const listener = typeof (args[0]) === 'function' ? args[0] : args[1]
260
- const parts = type ? type.split(this._delimiter) : []
261
- const hasWildcard = type ? type.includes('*') : false
262
- if (type && !hasWildcard) {
263
- this._traverseToPath(this.listeners, parts, (node) => {
264
- if (listener) { // 只删除指定的监听器
265
- this._removeListener(node, parts, listener)
266
- } else if (type) {
267
- node.__listeners = []
268
- }
269
- })
270
- } else { // 仅删除指定的侦听器
271
- const entryParts: string[] = hasWildcard ? [] : parts
272
- this._traverseListeners(this.listeners, entryParts, (path, node) => {
273
- if (listener !== undefined || (hasWildcard && isPathMatched(path, parts))) {
274
- if (listener) {
275
- this._removeListener(node, parts, listener)
276
- } else {
277
- node.__listeners = []
278
- }
279
- }
280
- })
281
- }
282
- }
283
-
284
- /**
285
- * 移除所有事件监听器
286
- * @param entry - 可选的事件前缀,如果提供则只移除指定前缀下的的监听器
287
- * @description
288
- * - 如果提供了prefix参数,则只清除该前缀下的所有监听器
289
- * - 如果没有提供prefix,则清除所有监听器
290
- * - 同时会清空保留的事件(_retainedEvents)
291
- * - 重置监听器对象为空
292
-
293
- * @example
294
- *
295
- * ```ts
296
- * emitter.offAll(); // 清除所有监听器
297
- * emitter.offAll('a/b'); // 清除a/b下的所有监听器
298
- *
299
- */
300
- offAll(entry?: string) {
301
- if (entry) {
302
- const entryNode = this._getListenerNode(entry.split(this._delimiter))
303
- if (entryNode) entryNode.__listeners = []
304
- this._removeRetainedEvents(entry)
305
- } else {
306
- this.retainedMessages.clear()
307
- this.listeners = { __listeners: [] } as unknown as FastListeners
308
- }
309
- if (typeof (this._options.onClearListeners) === 'function') this._options.onClearListeners.call(this)
310
- }
311
-
312
- private _getListenerNode(parts: string[]): FastListenerNode | undefined {
313
- let entryNode: FastListenerNode | undefined
314
- this._forEachNodes(parts, (node) => {
315
- entryNode = node
316
- })
317
- return entryNode
318
- }
319
- /**
320
- * 移除保留的事件
321
- * @param prefix - 事件前缀。如果不提供,将清除所有保留的事件。
322
- * 如果提供前缀,将删除所有以该前缀开头的事件。
323
- * 如果前缀不以分隔符结尾,会自动添加分隔符。
324
- * @private
325
- */
326
- private _removeRetainedEvents(prefix?: string) {
327
- if (!prefix) this.retainedMessages.clear()
328
- if (prefix?.endsWith(this._delimiter)) {
329
- prefix += this._delimiter
330
- }
331
- this.retainedMessages.delete(prefix!)
332
- for (let key of this.retainedMessages.keys()) {
333
- if (key.startsWith(prefix!)) {
334
- this.retainedMessages.delete(key)
335
- }
336
- }
337
- }
338
- clear() {
339
- this.offAll()
340
- }
341
-
342
- private _createMeta(extra: Record<string, any> | undefined) {
343
- if (!this._options.meta) return extra
344
- return Object.assign({}, this._options.meta, extra)
345
- }
346
-
347
-
348
- private _emitForLastEvent(type: string) {
349
- if (this.retainedMessages.has(type)) {
350
- const message = this.retainedMessages.get(type)
351
- const parts = type.split(this._delimiter);
352
- this._traverseToPath(this.listeners, parts, (node) => {
353
- this._executeListeners(node, message)
354
- })
355
- // onAny侦听器保存在根节点中,所以需要执行
356
- this._executeListeners(this.listeners, message)
357
- }
358
- }
359
-
360
- /**
361
- * 遍历监听器节点树
362
- * @param node 当前遍历的监听器节点
363
- * @param parts 事件名称按'.'分割的部分数组
364
- * @param callback 遍历到目标节点时的回调函数
365
- * @param index 当前遍历的parts数组索引,默认为0
366
- * @param lastFollowing 当命中**时该值为true, 注意**只能作在路径的最后面,如a.**有效,而a.**.b无效
367
- * @private
368
- *
369
- * 支持三种匹配模式:
370
- * - 精确匹配: 'a.b.c'
371
- * - 单层通配: 'a.*.c'
372
- * - 多层通配: 'a.**'
373
- */
374
- private _traverseToPath(node: FastListenerNode, parts: string[], callback: (node: FastListenerNode) => void, index: number = 0, lastFollowing?: boolean): void {
375
-
376
- if (index >= parts.length) {
377
- callback(node)
378
- return
379
- }
380
- const part = parts[index]
381
-
382
- if (lastFollowing === true) {
383
- this._traverseToPath(node, parts, callback, index + 1, true)
384
- return
385
- }
386
-
387
- if ('*' in node) {
388
- this._traverseToPath(node['*'], parts, callback, index + 1)
389
- }
390
- //
391
- if ('**' in node) {
392
- this._traverseToPath(node['**'], parts, callback, index + 1, true)
393
- }
394
-
395
- if (part in node) {
396
- this._traverseToPath(node[part], parts, callback, index + 1)
397
- }
398
- }
399
-
400
- private _traverseListeners(node: FastListenerNode, entry: string[], callback: (path: string[], node: FastListenerNode) => void): void {
401
- let entryNode: FastListenerNode = node
402
- // 如果指定了entry路径,则按照路径遍历
403
- if (entry && entry.length > 0) {
404
- this._traverseToPath(node, entry, (node) => {
405
- entryNode = node
406
- });
407
- }
408
- const traverseNodes = (node: FastListenerNode, callback: (path: string[], node: FastListenerNode) => void, parentPath: string[]) => {
409
- callback(parentPath, node);
410
- for (let [key, childNode] of Object.entries(node)) {
411
- if (key.startsWith("__")) continue
412
- if (childNode) {
413
- traverseNodes(childNode as FastListenerNode, callback, [...parentPath, key]);
414
- }
415
- }
416
- }
417
- // 如果没有指定entry或entry为空数组,则递归遍历所有节点
418
- traverseNodes(entryNode, callback, []);
419
- }
420
-
421
- /**
422
- * 执行单个监听器函数
423
- * @param listener - 要执行的监听器函数或包装过的监听器对象
424
- * @param message - 事件消息对象,包含type、payload和meta
425
- * @returns 监听器的执行结果或错误对象(如果配置了ignoreErrors)
426
- * @private
427
- *
428
- * @description
429
- * 执行单个监听器函数,处理以下情况:
430
- * - 如果监听器是包装过的(有__wrappedListener属性),调用包装的函数
431
- * - 否则直接调用监听器函数
432
- * - 使用配置的上下文(_context)作为this
433
- * - 捕获并处理执行过程中的错误:
434
- * - 如果有onListenerError回调,调用它
435
- * - 如果配置了ignoreErrors,返回错误对象
436
- * - 否则抛出错误
437
- */
438
- private _executeListener(listener: any, message: FastEventMessage): any {
439
- try {
440
- if (typeof (listener.__wrappedListener) === 'function') {
441
- return listener.__wrappedListener.call(this._context, message)
442
- } else {
443
- return listener.call(this._context, message)
444
- }
445
- } catch (e: any) {
446
- e._emitter = message.type
447
- if (typeof (this._options.onListenerError) === 'function') {
448
- this._options.onListenerError.call(this, message.type, e)
449
- }
450
- // 如果忽略错误,则返回错误对象
451
- if (this._options.ignoreErrors) {
452
- return e
453
- } else {
454
- throw e
455
- }
456
- }
457
- }
458
-
459
- /**
460
- * 执行监听器节点中的所有监听函数
461
- * @param node - FastListenerNode类型的监听器节点
462
- * @param payload - 事件携带的数据
463
- * @param type - 事件类型
464
- * @returns 返回所有监听函数的执行结果数组
465
- * @private
466
- *
467
- * @description
468
- * 遍历执行节点中的所有监听函数:
469
- * - 对于普通监听器,直接执行并收集结果
470
- * - 对于带次数限制的监听器(数组形式),执行后递减次数,当次数为0时移除该监听器
471
- */
472
- private _executeListeners(node: FastListenerNode, message: FastEventMessage): any[] {
473
- if (!node || !node.__listeners) return []
474
- let i = 0
475
- const listeners = node.__listeners
476
- let result: any[] = []
477
- while (i < listeners.length) {
478
- const listener = listeners[i]
479
- if (Array.isArray(listener)) {
480
- result.push(this._executeListener(listener[0], message))
481
- listener[1]--
482
- if (listener[1] === 0) {
483
- listeners.splice(i, 1)
484
- i-- // 抵消后面的i++
485
- }
486
- } else {
487
- result.push(this._executeListener(listener, message))
488
- }
489
- i++
490
- }
491
- return result
492
- }
493
- /**
494
- * 触发事件并执行对应的监听器
495
- *
496
- * @param type - 事件类型字符串或包含事件信息的对象
497
- * @param payload - 事件携带的数据负载
498
- * @param retain - 是否保留该事件(用于新订阅者)
499
- * @param meta - 事件元数据
500
- * @returns 所有监听器的执行结果数组
501
- *
502
- * @example
503
- * // 方式1: 参数形式
504
- * emit('user.login', { id: 1 }, true)
505
- *
506
- * // 方式2: 对象形式
507
- * emit({ type: 'user.login', payload: { id: 1 } ,meta:{...}}}, true)
508
- */
509
- /**
510
- * 同步触发事件
511
- * @param type - 事件类型,可以是字符串或预定义的事件类型
512
- * @param payload - 事件数据负载
513
- * @param retain - 是否保留该事件,用于后续新的订阅者
514
- * @param meta - 事件元数据
515
- * @returns 所有监听器的执行结果数组
516
- *
517
- * @description
518
- * 同步触发指定类型的事件,支持两种调用方式:
519
- * 1. 参数形式:emit(type, payload, retain, meta)
520
- * 2. 对象形式:emit({ type, payload, meta }, retain)
521
- *
522
- * 特性:
523
- * - 支持通配符匹配,一个事件可能触发多个监听器
524
- * - 如果设置了retain为true,会保存最后一次的事件数据
525
- * - 按照注册顺序同步调用所有匹配的监听器
526
- * - 如果配置了ignoreErrors,监听器抛出的错误会被捕获并返回
527
- *
528
- * @example
529
- * ```ts
530
- * // 简单事件触发
531
- * emitter.emit('user/login', { userId: 123 });
532
- *
533
- * // 带保留的事件触发
534
- * emitter.emit('status/change', { online: true }, true);
535
- *
536
- * // 带元数据的事件触发
537
- * emitter.emit('data/update', newData, false, { timestamp: Date.now() });
538
- *
539
- * // 使用对象形式触发
540
- * emitter.emit({
541
- * type: 'user/login',
542
- * payload: { userId: 123 },
543
- * meta: { time: Date.now() }
544
- * }, true);
545
- * ```
546
- */
547
- public emit<R = any>(type: string, payload?: any, retain?: boolean, meta?: Meta): R[]
548
- public emit<R = any>(type: Types, payload?: Events[Types], retain?: boolean, meta?: Meta): R[]
549
- public emit<R = any>(message: FastEventMessage<Types, Events[Types], Meta>, retain?: boolean): R[]
550
- public emit<R = any>(message: FastEventMessage<string, any, Meta>, retain?: boolean): R[]
551
- public emit<R = any>(): R[] {
552
- let type: string, payload: any, retain: boolean, meta: any
553
- if (typeof (arguments[0]) === 'object') {
554
- type = arguments[0].type as string
555
- payload = arguments[0].payload as any
556
- meta = this._createMeta(arguments[0].meta) as Meta
557
- retain = arguments[1] as boolean
558
- } else {
559
- type = arguments[0] as string
560
- payload = arguments[1] as any
561
- retain = arguments[2] as boolean
562
- meta = this._createMeta(arguments[3])
563
- }
564
- const message: FastEventMessage = {
565
- type,
566
- payload,
567
- meta
568
- }
569
- const parts = type.split(this._delimiter);
570
- if (retain) {
571
- this.retainedMessages.set(type, message)
572
- }
573
- const results: any[] = []
574
- // onAny侦听器保存在根节点中,所以需要执行
575
- results.push(...this._executeListeners(this.listeners, message))
576
- this._traverseToPath(this.listeners, parts, (node) => {
577
- results.push(...this._executeListeners(node, message))
578
- // 用于调试时使用
579
- if (this._options.debug && typeof (this._options.onExecuteListener) === 'function') {
580
- if (retain) {
581
- if (!message.meta) message.meta = { retain: true }
582
- }
583
- this._options.onExecuteListener.call(this, message, results, [...this.listeners.__listeners, ...node.__listeners])
584
- }
585
- })
586
-
587
- return results
588
- }
589
-
590
- /**
591
- * 异步触发事件
592
- * @param type - 事件类型,可以是字符串或预定义的事件类型
593
- * @param payload - 事件数据负载
594
- * @param retain - 是否保留该事件,用于后续新的订阅者
595
- * @param meta - 事件元数据
596
- * @returns Promise,解析为所有监听器的执行结果数组
597
- *
598
- * @description
599
- * 异步触发指定类型的事件,与emit方法类似,但有以下区别:
600
- * - 返回Promise,等待所有异步监听器执行完成
601
- * - 使用Promise.allSettled处理监听器的执行结果
602
- * - 即使某些监听器失败,也会等待所有监听器执行完成
603
- * - 返回结果包含成功值或错误信息
604
- *
605
- * @example
606
- * ```ts
607
- * // 异步事件处理
608
- * const results = await emitter.emitAsync('data/process', rawData);
609
- *
610
- * // 处理结果包含成功和失败的情况
611
- * results.forEach(result => {
612
- * if (result instanceof Error) {
613
- * console.error('处理失败:', result);
614
- * } else {
615
- * console.log('处理成功:', result);
616
- * }
617
- * });
618
- *
619
- * // 带元数据的异步事件
620
- * await emitter.emitAsync('batch/process', items, false, {
621
- * batchId: 'batch-001',
622
- * timestamp: Date.now()
623
- * });
624
- * ```
625
- */
626
- public async emitAsync<R = any>(type: string, payload?: any, retain?: boolean, meta?: Meta): Promise<[R | Error][]>
627
- public async emitAsync<R = any>(type: Types, payload?: Events[Types], retain?: boolean, meta?: Meta): Promise<[R | Error][]>
628
- public async emitAsync<P = any>(): Promise<[P | Error][]> {
629
- const type = arguments[0] as string
630
- const payload = arguments[1] as any
631
- const retain = arguments[2] as boolean
632
- const meta = this._createMeta((arguments[3])) as Meta
633
- const message = {
634
- type,
635
- payload,
636
- meta
637
- }
638
- const results = await Promise.allSettled(this.emit<P>(message, retain))
639
- return results.map((result) => {
640
- if (result.status === 'fulfilled') {
641
- return result.value
642
- } else {
643
- return result.reason
644
- }
645
- })
646
- }
647
-
648
- /**
649
- * 等待指定事件发生,返回一个Promise
650
- * @param type - 要等待的事件类型
651
- * @param timeout - 超时时间(毫秒),默认为0表示永不超时
652
- * @returns Promise,解析为事件消息对象,包含type、payload和meta
653
- *
654
- * @description
655
- * 创建一个Promise,在指定事件发生时解析。
656
- * - 当事件触发时,Promise会解析为事件消息对象
657
- * - 如果设置了timeout且超时,Promise会被拒绝
658
- * - 一旦事件发生或超时,会自动取消事件监听
659
- *
660
- * @example
661
- * ```ts
662
- * try {
663
- * // 等待登录事件,最多等待5秒
664
- * const event = await emitter.waitFor('user/login', 5000);
665
- * console.log('用户登录成功:', event.payload);
666
- * } catch (error) {
667
- * console.error('等待登录超时');
668
- * }
669
- *
670
- * // 无限等待事件
671
- * const event = await emitter.waitFor('server/ready');
672
- * console.log('服务器就绪');
673
- * ```
674
- */
675
- public waitFor<T extends Types, P = Events[T], M = Meta>(type: T, timeout?: number): Promise<FastEventMessage<T, P, M>>
676
- public waitFor<T extends string, P = Events[T], M = Meta>(type: string, timeout?: number): Promise<FastEventMessage<T, P, M>>
677
- public waitFor<T extends string, P = Events[T], M = Meta>(): Promise<FastEventMessage<T, P, M>> {
678
- const type = arguments[0] as any
679
- const timeout = arguments[1] as number
680
- return new Promise<FastEventMessage<T, P, M>>((resolve, reject) => {
681
- let tid: any
682
- let subscriber: FastEventSubscriber
683
- const listener = (message: FastEventMessage<T, P, M>) => {
684
- clearTimeout(tid)
685
- subscriber.off()
686
- resolve(message)
687
- }
688
- if (timeout && timeout > 0) {
689
- tid = setTimeout(() => {
690
- subscriber && subscriber.off()
691
- reject(new Error('wait for event<' + type + '> is timeout'))
692
- }, timeout)
693
- }
694
- subscriber = this.on(type, listener as any)
695
- })
696
- }
697
-
698
- /**
699
- * 创建一个新的事件作用域
700
- * @param prefix - 作用域前缀,将自动添加到该作用域下所有事件名称前
701
- * @returns 新的FastEventScope实例
702
- *
703
- * @description
704
- * 创建一个新的事件作用域,用于在特定命名空间下管理事件。
705
- *
706
- * 重要特性:
707
- * - 作用域与父事件发射器共享同一个监听器表
708
- * - 作用域中的事件会自动添加前缀
709
- * - 作用域的所有操作都会映射到父事件发射器上
710
- * - 作用域不是完全隔离的,只是提供了事件名称的命名空间
711
- *
712
- * @example
713
- * ```ts
714
- * const emitter = new FastEvent();
715
- *
716
- * // 创建用户相关事件的作用域
717
- * const userEvents = emitter.scope('user');
718
- *
719
- * // 在作用域中监听事件
720
- * userEvents.on('login', (data) => {
721
- * // 实际监听的是 'user/login'
722
- * console.log('用户登录:', data);
723
- * });
724
- *
725
- * // 在作用域中触发事件
726
- * userEvents.emit('login', { userId: 123 });
727
- * // 等同于 emitter.emit('user/login', { userId: 123 })
728
- *
729
- * // 创建嵌套作用域
730
- * const profileEvents = userEvents.scope('profile');
731
- * profileEvents.emit('update', { name: 'John' });
732
- * // 等同于 emitter.emit('user/profile/update', { name: 'John' })
733
- *
734
- * // 清理作用域
735
- * userEvents.offAll(); // 清理 'user' 前缀下的所有事件
736
- * ```
737
- */
738
- scope<T extends string>(prefix: T) {
739
- return new FastEventScope<ScopeEvents<Events, T>>(this as unknown as FastEvent<ScopeEvents<Events, T>>, prefix)
740
- }
741
- }