fastevent 1.0.4 → 1.1.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 (53) hide show
  1. package/.prettierrc.js +20 -0
  2. package/.vscode/settings.json +18 -0
  3. package/CHANGELOG.md +22 -6
  4. package/dist/devTools.d.mts +308 -0
  5. package/dist/devTools.d.ts +308 -0
  6. package/dist/devTools.js +3 -0
  7. package/dist/devTools.js.map +1 -0
  8. package/dist/devTools.mjs +3 -0
  9. package/dist/devTools.mjs.map +1 -0
  10. package/dist/index.d.mts +40 -17
  11. package/dist/index.d.ts +40 -17
  12. package/dist/index.js +1 -1
  13. package/dist/index.js.map +1 -1
  14. package/dist/index.mjs +1 -1
  15. package/dist/index.mjs.map +1 -1
  16. package/example/README.md +54 -0
  17. package/example/eslint.config.js +28 -0
  18. package/example/index.html +13 -0
  19. package/example/package.json +29 -0
  20. package/example/pnpm-lock.yaml +2047 -0
  21. package/example/public/vite.svg +1 -0
  22. package/example/src/App.css +42 -0
  23. package/example/src/App.tsx +60 -0
  24. package/example/src/assets/react.svg +1 -0
  25. package/example/src/index.css +68 -0
  26. package/example/src/main.tsx +10 -0
  27. package/example/src/vite-env.d.ts +1 -0
  28. package/example/tsconfig.app.json +26 -0
  29. package/example/tsconfig.json +7 -0
  30. package/example/tsconfig.node.json +24 -0
  31. package/example/vite.config.ts +7 -0
  32. package/package.json +15 -2
  33. package/readme.md +275 -66
  34. package/readme_cn.md +275 -70
  35. package/src/__tests__/emit.test.ts +68 -69
  36. package/src/__tests__/emitAsync.test.ts +41 -42
  37. package/src/__tests__/many.test.ts +15 -16
  38. package/src/__tests__/meta.test.ts +19 -19
  39. package/src/__tests__/off.test.ts +162 -162
  40. package/src/__tests__/onany.test.ts +97 -98
  41. package/src/__tests__/once.test.ts +42 -43
  42. package/src/__tests__/retain.test.ts +36 -36
  43. package/src/__tests__/scope.test.ts +38 -39
  44. package/src/__tests__/types.test.ts +97 -80
  45. package/src/__tests__/waitFor.test.ts +36 -29
  46. package/src/__tests__/wildcard.test.ts +114 -115
  47. package/src/devTools.ts +166 -0
  48. package/src/event.ts +272 -222
  49. package/src/scope.ts +64 -55
  50. package/src/types.ts +38 -34
  51. package/src/utils/WeakObjectMap.ts +64 -0
  52. package/tsconfig.json +103 -111
  53. package/tsup.config.ts +17 -6
package/src/event.ts CHANGED
@@ -1,52 +1,63 @@
1
1
  import { FastEventScope } from './scope';
2
- import {
3
- FastEventListener,
4
- FastEventOptions,
5
- FastEvents,
6
- FastListeners,
7
- FastListenerNode,
8
- FastEventSubscriber,
2
+ import {
3
+ FastEventListener,
4
+ FastEventOptions,
5
+ FastEvents,
6
+ FastListeners,
7
+ FastListenerNode,
8
+ FastEventSubscriber,
9
9
  ScopeEvents,
10
- FastEventMeta,
11
10
  FastEventListenOptions,
12
11
  FastEventMessage
13
- } from './types';
12
+ } from './types';
14
13
  import { isPathMatched } from './utils/isPathMatched';
15
14
  import { removeItem } from './utils/removeItem';
16
-
15
+
17
16
  export class FastEvent<
18
- Events extends FastEvents = FastEvents,
19
- Meta extends Record<string,any>=Record<string,any>,
20
- Types extends keyof Events = keyof Events
21
- >{
22
- public listeners : FastListeners = { __listeners: [] } as unknown as FastListeners
23
- private _options : FastEventOptions
24
- private _delimiter : string = '/'
25
- private _context : any
26
- private _retainedEvents : Map<string,any> = new Map<string,any>()
27
- constructor(options?:FastEventOptions<Meta>) {
17
+ Events extends FastEvents = FastEvents,
18
+ Meta extends Record<string, any> = Record<string, any>,
19
+ Types extends keyof Events = keyof Events
20
+ > {
21
+ public listeners: FastListeners = { __listeners: [] } as unknown as FastListeners
22
+ private _options: FastEventOptions
23
+ private _delimiter: string = '/'
24
+ private _context: any
25
+ retainedMessages: Map<string, any> = new Map<string, any>()
26
+ listenerCount: number = 0
27
+ constructor(options?: FastEventOptions<Meta>) {
28
28
  this._options = Object.assign({
29
- delimiter : '/',
30
- context : null,
31
- ignoreErrors : true
29
+ debug: false,
30
+ id: Math.random().toString(36).substring(2),
31
+ delimiter: '/',
32
+ context: null,
33
+ ignoreErrors: true
32
34
  }, options)
33
35
  this._delimiter = this._options.delimiter!
34
36
  this._context = this._options.context || this
37
+ this._enableDevTools()
35
38
  }
36
- get options(){ return this._options }
37
- private _addListener(parts:string[],listener:FastEventListener<any,any>,options:Required<FastEventListenOptions>):FastListenerNode | undefined{
39
+ get options() { return this._options }
40
+ get id() { return this._options.id! }
41
+ private _addListener(parts: string[], listener: FastEventListener<any, any>, options: Required<FastEventListenOptions>): FastListenerNode | undefined {
38
42
  const { count, prepend } = options
39
- return this._forEachNodes(parts,(node)=>{
40
- const newListener = count >0 ? [listener,count]: listener as any
41
- if(prepend){
42
- node.__listeners.splice(0,0,newListener)
43
- }else{
43
+ return this._forEachNodes(parts, (node) => {
44
+ const newListener = count > 0 ? [listener, count] : listener as any
45
+ if (prepend) {
46
+ node.__listeners.splice(0, 0, newListener)
47
+ } else {
44
48
  node.__listeners.push(newListener)
45
- }
46
- if(typeof(this._options.onAddListener)==='function'){
47
- this._options.onAddListener(parts,listener)
48
49
  }
49
- })
50
+ if (typeof (this._options.onAddListener) === 'function') {
51
+ this.listenerCount++
52
+ this._options.onAddListener(parts, listener)
53
+ }
54
+ })
55
+ }
56
+ private _enableDevTools() {
57
+ if (this.options.debug) {
58
+ // @ts-ignore
59
+ globalThis.__FLEXEVENT_DEVTOOLS__.add(this)
60
+ }
50
61
  }
51
62
  /**
52
63
  *
@@ -56,26 +67,26 @@ export class FastEvent<
56
67
  * @param callback
57
68
  * @returns
58
69
  */
59
- private _forEachNodes(parts:string[],callback:(node:FastListenerNode,parent:FastListenerNode)=>void):FastListenerNode | undefined{
60
- if(parts.length === 0) return
70
+ private _forEachNodes(parts: string[], callback: (node: FastListenerNode, parent: FastListenerNode) => void): FastListenerNode | undefined {
71
+ if (parts.length === 0) return
61
72
  let current = this.listeners
62
- for(let i=0;i<parts.length;i++){
73
+ for (let i = 0; i < parts.length; i++) {
63
74
  const part = parts[i]
64
- if(!(part in current)){
75
+ if (!(part in current)) {
65
76
  current[part] = {
66
77
  __listeners: []
67
78
  } as unknown as FastListeners
68
79
  }
69
- if(i===parts.length-1){
80
+ if (i === parts.length - 1) {
70
81
  const node = current[part]
71
- callback(node,current)
82
+ callback(node, current)
72
83
  return node
73
- }else{
84
+ } else {
74
85
  current = current[part]
75
86
  }
76
87
  }
77
88
  return undefined
78
- }
89
+ }
79
90
 
80
91
 
81
92
  /**
@@ -85,49 +96,51 @@ export class FastEvent<
85
96
  * @param listener - 需要移除的事件监听器
86
97
  * @description 遍历节点的监听器列表,移除所有匹配的监听器。支持移除普通函数和数组形式的监听器
87
98
  */
88
- private _removeListener(node: FastListenerNode, path:string[],listener: FastEventListener<any,any,any>): void {
89
- if(!listener) return
90
- removeItem(node.__listeners,(item:any)=>{
91
- item = Array.isArray(item) ? item[0] : item
92
- const isRemove = item === listener
93
- if(isRemove && typeof(this._options.onRemoveListener)==='function'){
94
- this._options.onRemoveListener(path,listener)
99
+ private _removeListener(node: FastListenerNode, path: string[], listener: FastEventListener<any, any, any>): void {
100
+ if (!listener) return
101
+ removeItem(node.__listeners, (item: any) => {
102
+ item = Array.isArray(item) ? item[0] : item
103
+ const isRemove = item === listener
104
+ if (isRemove && typeof (this._options.onRemoveListener) === 'function') {
105
+ this.listenerCount--
106
+ this._options.onRemoveListener(path, listener)
95
107
  }
96
108
  return isRemove
97
- })
109
+ })
98
110
  }
99
- public on<T extends string>(type: T, listener: FastEventListener<T,Events[T],Meta>, options?:FastEventListenOptions ): FastEventSubscriber
100
- public on<T extends Types=Types>(type: T, listener: FastEventListener<Types,Events[T],Meta>, options?:FastEventListenOptions): FastEventSubscriber
101
- public on<P=any>(type: '**', listener: FastEventListener<Types,P,Meta>): FastEventSubscriber
102
- public on(): FastEventSubscriber{
111
+ public on<T extends string>(type: T, listener: FastEventListener<T, Events[T], Meta>, options?: FastEventListenOptions): FastEventSubscriber
112
+ public on<T extends Types = Types>(type: T, listener: FastEventListener<Types, Events[T], Meta>, options?: FastEventListenOptions): FastEventSubscriber
113
+ public on<P = any>(type: '**', listener: FastEventListener<Types, P, Meta>): FastEventSubscriber
114
+ public on(): FastEventSubscriber {
103
115
  const type = arguments[0] as string
104
- const listener = arguments[1] as FastEventListener
116
+ const listener = arguments[1] as FastEventListener
105
117
  const options = Object.assign({
106
- count : 0,
118
+ count: 0,
107
119
  prepend: false
108
- },arguments[2]) as Required<FastEventListenOptions>
120
+ }, arguments[2]) as Required<FastEventListenOptions>
109
121
 
110
- if(type.length===0) throw new Error('event type cannot be empty')
122
+ if (type.length === 0) throw new Error('event type cannot be empty')
111
123
 
112
- if(type==='**'){
124
+ if (type === '**') {
113
125
  return this.onAny(listener)
114
126
  }
115
127
 
116
128
  const parts = type.split(this._delimiter);
117
- const node = this._addListener(parts,listener,options)
118
-
129
+ const node = this._addListener(parts, listener, options)
130
+
119
131
  // Retain不支持通配符
120
- if(node && !type.includes('*')) this._emitForLastEvent(type)
132
+ if (node && !type.includes('*')) this._emitForLastEvent(type)
121
133
 
122
134
  return {
123
- off: ()=>node && this._removeListener(node,parts,listener)
135
+ off: () => node && this._removeListener(node, parts, listener)
124
136
  }
125
- }
137
+ }
126
138
 
127
- public once<T extends string>(type: T, listener: FastEventListener<T,Events[T],Meta> ): FastEventSubscriber
128
- public once<T extends Types=Types>(type: T, listener: FastEventListener<Types,Events[T],Meta> ): FastEventSubscriber
129
- public once(): FastEventSubscriber{
130
- return this.on(arguments[0],arguments[1],{count:1})
139
+
140
+ public once<T extends Types = Types>(type: T, listener: FastEventListener<T, Events[T], Meta>): FastEventSubscriber
141
+ public once<T extends string>(type: T, listener: FastEventListener<T, Events[T], Meta>): FastEventSubscriber
142
+ public once(): FastEventSubscriber {
143
+ return this.on(arguments[0], arguments[1], { count: 1 })
131
144
  }
132
145
 
133
146
  /**
@@ -144,51 +157,51 @@ export class FastEvent<
144
157
  * subscriber.off();
145
158
  * ```
146
159
  */
147
- onAny<P=any>(listener: FastEventListener<string,P,Meta>, options?:Pick<FastEventListenOptions,'prepend'>): FastEventSubscriber {
160
+ onAny<P = any>(listener: FastEventListener<string, P, Meta>, options?: Pick<FastEventListenOptions, 'prepend'>): FastEventSubscriber {
148
161
  const listeners = this.listeners.__listeners
149
- if(options && options.prepend){
150
- listeners.splice(0,0,listener)
151
- }else{
162
+ if (options && options.prepend) {
163
+ listeners.splice(0, 0, listener)
164
+ } else {
152
165
  listeners.push(listener)
153
- }
166
+ }
154
167
  return {
155
- off:()=>this._removeListener(this.listeners,[],listener)
168
+ off: () => this._removeListener(this.listeners, [], listener)
156
169
  }
157
170
  }
158
171
 
159
- off(listener: FastEventListener<any, any, any>):void
160
- off(type: string, listener: FastEventListener<any, any, any>):void
161
- off(type: Types, listener: FastEventListener<any, any, any>):void
162
- off(type: string):void
163
- off(type: Types):void
164
- off(){
172
+ off(listener: FastEventListener<any, any, any>): void
173
+ off(type: string, listener: FastEventListener<any, any, any>): void
174
+ off(type: Types, listener: FastEventListener<any, any, any>): void
175
+ off(type: string): void
176
+ off(type: Types): void
177
+ off() {
165
178
  const args = arguments
166
- const type = typeof(args[0])==='function' ? undefined : args[0]
167
- const listener = typeof(args[0])==='function' ? args[0] : args[1]
179
+ const type = typeof (args[0]) === 'function' ? undefined : args[0]
180
+ const listener = typeof (args[0]) === 'function' ? args[0] : args[1]
168
181
  const parts = type ? type.split(this._delimiter) : []
169
- const hasWildcard= type ? type.includes('*') : false
170
- if(type && !hasWildcard){
171
- this._traverseToPath(this.listeners,parts,(node)=>{
172
- if(listener){ // 只删除指定的监听器
173
- this._removeListener(node,parts,listener)
174
- }else if(type){
175
- node.__listeners=[]
182
+ const hasWildcard = type ? type.includes('*') : false
183
+ if (type && !hasWildcard) {
184
+ this._traverseToPath(this.listeners, parts, (node) => {
185
+ if (listener) { // 只删除指定的监听器
186
+ this._removeListener(node, parts, listener)
187
+ } else if (type) {
188
+ node.__listeners = []
176
189
  }
177
190
  })
178
- }else{ // 仅删除指定的侦听器
179
- const entryParts:string[] = hasWildcard ? [] : parts
180
- this._traverseListeners(this.listeners,entryParts,(path,node)=>{
181
- if(listener!==undefined || (hasWildcard && isPathMatched(path,parts))){
182
- if(listener){
183
- this._removeListener(node,parts,listener)
184
- }else{
185
- node.__listeners=[]
186
- }
191
+ } else { // 仅删除指定的侦听器
192
+ const entryParts: string[] = hasWildcard ? [] : parts
193
+ this._traverseListeners(this.listeners, entryParts, (path, node) => {
194
+ if (listener !== undefined || (hasWildcard && isPathMatched(path, parts))) {
195
+ if (listener) {
196
+ this._removeListener(node, parts, listener)
197
+ } else {
198
+ node.__listeners = []
199
+ }
187
200
  }
188
201
  })
189
202
  }
190
203
  }
191
-
204
+
192
205
  /**
193
206
  * 移除所有事件监听器
194
207
  * @param entry - 可选的事件前缀,如果提供则只移除指定前缀下的的监听器
@@ -205,20 +218,21 @@ export class FastEvent<
205
218
  * emitter.offAll('a/b'); // 清除a/b下的所有监听器
206
219
  *
207
220
  */
208
- offAll(entry?: string) {
209
- if(entry){
221
+ offAll(entry?: string) {
222
+ if (entry) {
210
223
  const entryNode = this._getListenerNode(entry.split(this._delimiter))
211
- if(entryNode) entryNode.__listeners = []
224
+ if (entryNode) entryNode.__listeners = []
212
225
  this._removeRetainedEvents(entry)
213
- }else{
214
- this._retainedEvents.clear()
226
+ } else {
227
+ this.retainedMessages.clear()
215
228
  this.listeners = { __listeners: [] } as unknown as FastListeners
216
229
  }
230
+ if (typeof (this._options.onClearListeners) === 'function') this._options.onClearListeners.call(this)
217
231
  }
218
232
 
219
- private _getListenerNode(parts:string[]):FastListenerNode | undefined{
233
+ private _getListenerNode(parts: string[]): FastListenerNode | undefined {
220
234
  let entryNode: FastListenerNode | undefined
221
- this._forEachNodes(parts,(node)=>{
235
+ this._forEachNodes(parts, (node) => {
222
236
  entryNode = node
223
237
  })
224
238
  return entryNode
@@ -231,34 +245,37 @@ export class FastEvent<
231
245
  * @private
232
246
  */
233
247
  private _removeRetainedEvents(prefix?: string) {
234
- if (!prefix) this._retainedEvents.clear()
235
- if(prefix?.endsWith(this._delimiter)){
236
- prefix+=this._delimiter
237
- }
238
- this._retainedEvents.delete(prefix!)
239
- for(let key of this._retainedEvents.keys()){
240
- if(key.startsWith(prefix!)){
241
- this._retainedEvents.delete(key)
248
+ if (!prefix) this.retainedMessages.clear()
249
+ if (prefix?.endsWith(this._delimiter)) {
250
+ prefix += this._delimiter
251
+ }
252
+ this.retainedMessages.delete(prefix!)
253
+ for (let key of this.retainedMessages.keys()) {
254
+ if (key.startsWith(prefix!)) {
255
+ this.retainedMessages.delete(key)
242
256
  }
243
257
  }
244
- }
245
- clear(){
258
+ }
259
+ clear() {
246
260
  this.offAll()
247
261
  }
248
- private _getMeta(extra:Record<string,any>){
249
- if(!this._options.meta) return extra
250
- return Object.assign({},this._options.meta,extra) as FastEventMeta<any,any>
262
+
263
+ private _createMeta(extra: Record<string, any> | undefined) {
264
+ if (!this._options.meta) return extra
265
+ return Object.assign({}, this._options.meta, extra)
251
266
  }
252
- private _emitForLastEvent(type:string){
253
- if(this._retainedEvents.has(type)){
254
- const payload = this._retainedEvents.get(type)
255
- const parts = type.split(this._delimiter);
256
- this._traverseToPath(this.listeners,parts,(node)=>{
257
- this._executeListeners(node,payload,this._getMeta({type}))
258
- })
267
+
268
+
269
+ private _emitForLastEvent(type: string) {
270
+ if (this.retainedMessages.has(type)) {
271
+ const message = this.retainedMessages.get(type)
272
+ const parts = type.split(this._delimiter);
273
+ this._traverseToPath(this.listeners, parts, (node) => {
274
+ this._executeListeners(node, message)
275
+ })
259
276
  // onAny侦听器保存在根节点中,所以需要执行
260
- this._executeListeners(this.listeners,payload,this._getMeta({type}))
261
- }
277
+ this._executeListeners(this.listeners, message)
278
+ }
262
279
  }
263
280
 
264
281
  /**
@@ -275,25 +292,25 @@ export class FastEvent<
275
292
  * - 单层通配: 'a.*.c'
276
293
  * - 多层通配: 'a.**'
277
294
  */
278
- private _traverseToPath(node: FastListenerNode, parts: string[], callback: (node: FastListenerNode) => void, index: number = 0, lastFollowing?:boolean): void {
295
+ private _traverseToPath(node: FastListenerNode, parts: string[], callback: (node: FastListenerNode) => void, index: number = 0, lastFollowing?: boolean): void {
279
296
 
280
297
  if (index >= parts.length) {
281
298
  callback(node)
282
299
  return
283
- }
284
- const part = parts[index]
300
+ }
301
+ const part = parts[index]
285
302
 
286
- if(lastFollowing===true){
287
- this._traverseToPath(node, parts, callback, index + 1,true)
303
+ if (lastFollowing === true) {
304
+ this._traverseToPath(node, parts, callback, index + 1, true)
288
305
  return
289
306
  }
290
307
 
291
308
  if ('*' in node) {
292
309
  this._traverseToPath(node['*'], parts, callback, index + 1)
293
- }
310
+ }
294
311
  //
295
312
  if ('**' in node) {
296
- this._traverseToPath(node['**'], parts, callback, index + 1,true)
313
+ this._traverseToPath(node['**'], parts, callback, index + 1, true)
297
314
  }
298
315
 
299
316
  if (part in node) {
@@ -301,43 +318,43 @@ export class FastEvent<
301
318
  }
302
319
  }
303
320
 
304
- private _traverseListeners(node: FastListenerNode, entry:string[], callback: (path:string[],node: FastListenerNode) => void): void {
321
+ private _traverseListeners(node: FastListenerNode, entry: string[], callback: (path: string[], node: FastListenerNode) => void): void {
305
322
  let entryNode: FastListenerNode = node
306
323
  // 如果指定了entry路径,则按照路径遍历
307
- if (entry && entry.length > 0) {
308
- this._traverseToPath(node, entry,(node)=>{
309
- entryNode= node
324
+ if (entry && entry.length > 0) {
325
+ this._traverseToPath(node, entry, (node) => {
326
+ entryNode = node
310
327
  });
311
328
  }
312
- const traverseNodes = (node: FastListenerNode, callback: (path:string[],node: FastListenerNode) => void,parentPath:string[])=>{
313
- callback(parentPath, node);
314
- for(let [key,childNode] of Object.entries(node)){
315
- if(key.startsWith("__")) continue
316
- if(childNode){
317
- traverseNodes(childNode as FastListenerNode, callback,[...parentPath,key]);
329
+ const traverseNodes = (node: FastListenerNode, callback: (path: string[], node: FastListenerNode) => void, parentPath: string[]) => {
330
+ callback(parentPath, node);
331
+ for (let [key, childNode] of Object.entries(node)) {
332
+ if (key.startsWith("__")) continue
333
+ if (childNode) {
334
+ traverseNodes(childNode as FastListenerNode, callback, [...parentPath, key]);
318
335
  }
319
336
  }
320
337
  }
321
338
  // 如果没有指定entry或entry为空数组,则递归遍历所有节点
322
- traverseNodes(entryNode, callback,[]);
323
- }
339
+ traverseNodes(entryNode, callback, []);
340
+ }
324
341
 
325
- private _executeListener(listener:any, payload: any,meta: FastEventMeta<any,any> ):any{
326
- try{
327
- if(typeof(listener.__wrappedListener)==='function'){
328
- return listener.__wrappedListener.call(this._context,payload,meta)
329
- }else{
330
- return listener.call(this._context,payload,meta)
342
+ private _executeListener(listener: any, message: FastEventMessage): any {
343
+ try {
344
+ if (typeof (listener.__wrappedListener) === 'function') {
345
+ return listener.__wrappedListener.call(this._context, message)
346
+ } else {
347
+ return listener.call(this._context, message)
331
348
  }
332
- }catch(e:any){
333
- e._trigger = meta.type
334
- if(typeof(this._options.onListenerError)==='function'){
335
- this._options.onListenerError.call(this,meta.type,e)
349
+ } catch (e: any) {
350
+ e._emitter = message.type
351
+ if (typeof (this._options.onListenerError) === 'function') {
352
+ this._options.onListenerError.call(this, message.type, e)
336
353
  }
337
354
  // 如果忽略错误,则返回错误对象
338
- if(this._options.ignoreErrors){
355
+ if (this._options.ignoreErrors) {
339
356
  return e
340
- }else{
357
+ } else {
341
358
  throw e
342
359
  }
343
360
  }
@@ -356,103 +373,137 @@ export class FastEvent<
356
373
  * - 对于普通监听器,直接执行并收集结果
357
374
  * - 对于带次数限制的监听器(数组形式),执行后递减次数,当次数为0时移除该监听器
358
375
  */
359
- private _executeListeners(node: FastListenerNode, payload: any, meta: Meta): any[] {
376
+ private _executeListeners(node: FastListenerNode, message: FastEventMessage): any[] {
360
377
  if (!node || !node.__listeners) return []
361
378
  let i = 0
362
379
  const listeners = node.__listeners
363
- let result:any[] = []
364
- while(i<listeners.length){
380
+ let result: any[] = []
381
+ while (i < listeners.length) {
365
382
  const listener = listeners[i]
366
- if(Array.isArray(listener)){
367
- result.push(this._executeListener(listener[0],payload,meta))
368
- listener[1]--
369
- if(listener[1]===0) {
370
- listeners.splice(i,1)
383
+ if (Array.isArray(listener)) {
384
+ result.push(this._executeListener(listener[0], message))
385
+ listener[1]--
386
+ if (listener[1] === 0) {
387
+ listeners.splice(i, 1)
371
388
  i-- // 抵消后面的i++
372
389
  }
373
- }else{
374
- result.push(this._executeListener(listener,payload,meta))
375
- }
376
- i++
390
+ } else {
391
+ result.push(this._executeListener(listener, message))
392
+ }
393
+ i++
377
394
  }
378
395
  return result
379
396
  }
380
-
381
- public emit<R=any>(type:string,payload?:any,retain?:boolean,meta?:Meta):R[]
382
- public emit<R=any>(type:Types,payload?:Events[Types],retain?:boolean,meta?:Meta):R[]
383
- public emit<R=any>(message:FastEventMessage<Types,Events[Types],Meta>,retain?:boolean):R[]
384
- public emit<R=any>(message:FastEventMessage<string,any,Meta>,retain?:boolean):R[]
385
- public emit<R=any>():R[]{
386
- let type:string,payload:any,retain:boolean,meta:Meta
387
- if(typeof(arguments[0])==='object'){
397
+ /**
398
+ * 触发事件并执行对应的监听器
399
+ *
400
+ * @param type - 事件类型字符串或包含事件信息的对象
401
+ * @param payload - 事件携带的数据负载
402
+ * @param retain - 是否保留该事件(用于新订阅者)
403
+ * @param meta - 事件元数据
404
+ * @returns 所有监听器的执行结果数组
405
+ *
406
+ * @example
407
+ * // 方式1: 参数形式
408
+ * emit('user.login', { id: 1 }, true)
409
+ *
410
+ * // 方式2: 对象形式
411
+ * emit({ type: 'user.login', payload: { id: 1 } ,meta:{...}}}, true)
412
+ */
413
+ public emit<R = any>(type: string, payload?: any, retain?: boolean, meta?: Meta): R[]
414
+ public emit<R = any>(type: Types, payload?: Events[Types], retain?: boolean, meta?: Meta): R[]
415
+ public emit<R = any>(message: FastEventMessage<Types, Events[Types], Meta>, retain?: boolean): R[]
416
+ public emit<R = any>(message: FastEventMessage<string, any, Meta>, retain?: boolean): R[]
417
+ public emit<R = any>(): R[] {
418
+ let type: string, payload: any, retain: boolean, meta: any
419
+ if (typeof (arguments[0]) === 'object') {
388
420
  type = arguments[0].type as string
389
421
  payload = arguments[0].payload as any
390
- meta = (arguments[0]).meta as Meta
391
- retain = arguments[1] as boolean
392
- }else{
422
+ meta = this._createMeta(arguments[0].meta) as Meta
423
+ retain = arguments[1] as boolean
424
+ } else {
393
425
  type = arguments[0] as string
394
426
  payload = arguments[1] as any
395
427
  retain = arguments[2] as boolean
396
- meta = (arguments[3] || {}) as Meta
397
- }
398
- const parts = type.split(this._delimiter);
399
- if(retain) {
400
- this._retainedEvents.set(type,payload)
401
- }
402
- const results:any[] = []
428
+ meta = this._createMeta(arguments[3])
429
+ }
430
+ const message: FastEventMessage = {
431
+ type,
432
+ payload,
433
+ meta
434
+ }
435
+ const parts = type.split(this._delimiter);
436
+ if (retain) {
437
+ this.retainedMessages.set(type, message)
438
+ }
439
+ const results: any[] = []
403
440
  // onAny侦听器保存在根节点中,所以需要执行
404
- results.push(...this._executeListeners(this.listeners,payload,this._getMeta({...meta,type})))
405
- this._traverseToPath(this.listeners,parts,(node)=>{
406
- results.push(...this._executeListeners(node,payload,this._getMeta({...meta,type})))
407
- })
441
+ results.push(...this._executeListeners(this.listeners, message))
442
+ this._traverseToPath(this.listeners, parts, (node) => {
443
+ results.push(...this._executeListeners(node, message))
444
+ // 用于调试时使用
445
+ if (this._options.debug && typeof (this._options.onExecuteListener) === 'function') {
446
+ if (retain) {
447
+ if (!message.meta) message.meta = { retain: true }
448
+ }
449
+ this._options.onExecuteListener.call(this, message, results, [...this.listeners.__listeners, ...node.__listeners])
450
+ }
451
+ })
452
+
408
453
  return results
409
454
  }
410
455
 
411
- public async emitAsync<R=any>(type:string,payload?:any,retain?:boolean,meta?:Meta):Promise<[R|Error][]>
412
- public async emitAsync<R=any>(type:Types,payload?:Events[Types],retain?:boolean,meta?:Meta):Promise<[R|Error][]>
413
- public async emitAsync<P=any>():Promise<[P|Error][]>{
456
+ public async emitAsync<R = any>(type: string, payload?: any, retain?: boolean, meta?: Meta): Promise<[R | Error][]>
457
+ public async emitAsync<R = any>(type: Types, payload?: Events[Types], retain?: boolean, meta?: Meta): Promise<[R | Error][]>
458
+ public async emitAsync<P = any>(): Promise<[P | Error][]> {
414
459
  const type = arguments[0] as string
415
460
  const payload = arguments[1] as any
416
461
  const retain = arguments[2] as boolean
417
- const meta = (arguments[3] || {}) as Meta
418
-
419
- const results = await Promise.allSettled(this.emit<P>(type,payload,retain,this._getMeta({...meta,type})))
420
- return results.map((result)=>{
421
- if(result.status==='fulfilled'){
462
+ const meta = this._createMeta((arguments[3])) as Meta
463
+ const message = {
464
+ type,
465
+ payload,
466
+ meta
467
+ }
468
+ const results = await Promise.allSettled(this.emit<P>(message, retain))
469
+ return results.map((result) => {
470
+ if (result.status === 'fulfilled') {
422
471
  return result.value
423
- }else{
472
+ } else {
424
473
  return result.reason
425
474
  }
426
475
  })
427
476
  }
428
477
 
429
478
  /**
430
- * 等待指定事件发生
479
+ * 等待指定事件发生
480
+ *
481
+ * waitFor("x")
431
482
  *
432
483
  * @param type
433
484
  * @param timeout 超时时间,单位毫秒,默认为 0,表示无限等待
434
485
  */
435
- public waitFor<R=any>(type:string,timeout?:number):Promise<R>
436
- public waitFor<R=any>(type:Types,timeout?:number):Promise<R>
437
- public waitFor<R=any>():Promise<R>{
438
- const type = arguments[0] as string
486
+ public waitFor<T extends Types, P = Events[T], M = Meta>(type: T, timeout?: number): Promise<FastEventMessage<T, P, M>>
487
+ public waitFor<T extends string, P = Events[T], M = Meta>(type: string, timeout?: number): Promise<FastEventMessage<T, P, M>>
488
+ public waitFor<T extends string, P = Events[T], M = Meta>(): Promise<FastEventMessage<T, P, M>> {
489
+ const type = arguments[0] as any
439
490
  const timeout = arguments[1] as number
440
- return new Promise<R>((resolve,reject)=>{
441
- let tid:any
442
- let subscriber:FastEventSubscriber
443
- const listener = (payload:any)=>{
491
+ return new Promise<FastEventMessage<T, P, M>>((resolve, reject) => {
492
+ let tid: any
493
+ let subscriber: FastEventSubscriber
494
+ const listener = (message: FastEventMessage<T, P, M>) => {
444
495
  clearTimeout(tid)
445
- subscriber.off()
446
- resolve(payload)
496
+ subscriber.off()
497
+ resolve(message)
447
498
  }
448
- if(timeout && timeout>0){
449
- tid = setTimeout(()=>{
499
+ if (timeout && timeout > 0) {
500
+ tid = setTimeout(() => {
450
501
  subscriber && subscriber.off()
451
- reject(new Error('wait for event<'+ type +'> is timeout'))
452
- },timeout)
502
+ reject(new Error('wait for event<' + type + '> is timeout'))
503
+ }, timeout)
453
504
  }
454
- subscriber = this.on(type,listener)
455
- })
505
+ subscriber = this.on(type, listener as any)
506
+ })
456
507
  }
457
508
 
458
509
  /**
@@ -473,8 +524,7 @@ export class FastEvent<
473
524
  * scope.offAll() == emitter.offAll("a/b")
474
525
  *
475
526
  */
476
- scope<T extends string>(prefix:T){
477
- return new FastEventScope<ScopeEvents<Events,T>>(this as unknown as FastEvent<ScopeEvents<Events,T>>,prefix)
527
+ scope<T extends string>(prefix: T) {
528
+ return new FastEventScope<ScopeEvents<Events, T>>(this as unknown as FastEvent<ScopeEvents<Events, T>>, prefix)
478
529
  }
479
-
480
530
  }