fastevent 1.0.3 → 1.1.0
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/.prettierrc.js +20 -0
- package/.vscode/settings.json +18 -0
- package/CHANGELOG.md +17 -5
- package/dist/index.d.mts +30 -10
- package/dist/index.d.ts +30 -10
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/readme.md +191 -66
- package/readme_cn.md +192 -67
- package/src/__tests__/emit.test.ts +73 -61
- package/src/__tests__/emitAsync.test.ts +41 -42
- package/src/__tests__/many.test.ts +15 -16
- package/src/__tests__/meta.test.ts +20 -21
- package/src/__tests__/off.test.ts +162 -162
- package/src/__tests__/onany.test.ts +97 -98
- package/src/__tests__/once.test.ts +42 -43
- package/src/__tests__/retain.test.ts +36 -36
- package/src/__tests__/scope.test.ts +38 -39
- package/src/__tests__/types.test.ts +134 -0
- package/src/__tests__/waitFor.test.ts +35 -29
- package/src/__tests__/wildcard.test.ts +114 -115
- package/src/event.ts +250 -213
- package/src/scope.ts +56 -55
- package/src/types.ts +33 -28
- package/src/typestest.ts +0 -102
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/scope.ts","../src/utils/isPathMatched.ts","../src/utils/removeItem.ts","../src/event.ts"],"names":["FastEventScope","constructor","emitter","prefix","length","endsWith","options","delimiter","_getScopeListener","listener","scopePrefix","scopeListener","__name","payload","type","startsWith","substring","__wrappedListener","_getScopeType","undefined","on","args","arguments","once","Object","assign","count","onAny","offAll","off","clear","emit","retain","waitFor","timeout","scope","_FastEventScope","isPathMatched","path","pattern","fPattern","splice","Array","from","fill","i","removeItem","arr","condition","index","findIndex","item","push","FastEvent","listeners","__listeners","_options","_delimiter","_context","_retainedEvents","Map","context","ignoreErrors","_addListener","parts","prepend","_forEachNodes","node","newListener","onAddListener","callback","current","part","_removeListener","isArray","isRemove","onRemoveListener","Error","split","includes","_emitForLastEvent","hasWildcard","_traverseToPath","entryParts","_traverseListeners","entry","entryNode","_getListenerNode","_removeRetainedEvents","delete","key","keys","_getMeta","extra","meta","has","get","_executeListeners","lastFollowing","traverseNodes","parentPath","childNode","entries","_executeListener","call","e","_trigger","onListenerError","result","set","results","emitAsync","Promise","allSettled","map","status","value","reason","resolve","reject","tid","subscriber","clearTimeout","setTimeout","_FastEvent"],"mappings":"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","file":"index.mjs","sourcesContent":["import { FastEvent } from \"./event\";\nimport { FastEventListener, FastEventListenOptions, FastEvents, FastEventSubscriber } from \"./types\";\n\nexport class FastEventScope<\n Events extends FastEvents = FastEvents, \n Types extends keyof Events = keyof Events,\n Meta = unknown\n>{\n constructor(public emitter:FastEvent<Events,Types,Meta>,public prefix:string){\n if(prefix.length>0 && !prefix.endsWith(emitter.options.delimiter!)){\n this.prefix = prefix + emitter.options.delimiter\n } \n }\n private _getScopeListener(listener:FastEventListener):FastEventListener{\n const scopePrefix = this.prefix\n if(scopePrefix.length===0) return listener\n const scopeListener = function(payload:any,{type}:{type:string}){\n if(type.startsWith(scopePrefix)){ \n type = type.substring(scopePrefix.length)\n }\n return listener(payload,{type})\n } \n // 当启用scope时对监听器进行包装\n //@ts-ignore\n listener.__wrappedListener = scopeListener\n return listener\n }\n private _getScopeType(type:string){\n return type===undefined ? undefined : this.prefix + type\n } \n \n public on<T extends string>(type: T, listener: FastEventListener<T,Events[T],Meta>, options?:FastEventListenOptions ): FastEventSubscriber \n public on<T extends Types=Types>(type: T, listener: FastEventListener<T,Events[T],Meta>, options?:FastEventListenOptions): FastEventSubscriber \n public on(type: '**', listener: FastEventListener<any,any,Meta>): FastEventSubscriber\n public on(): FastEventSubscriber{\n const args = [...arguments] as [any,any,any]\n args[0] = this._getScopeType(args[0])\n args[1] = this._getScopeListener(args[1])\n return this.emitter.on(...args)\n }\n\n public once<T extends string>(type: T, listener: FastEventListener<T,Events[T],Meta>, options?:FastEventListenOptions ): FastEventSubscriber\n public once<T extends Types = Types>(type: T, listener: FastEventListener<Types,Events[T],Meta>, options?:FastEventListenOptions ): FastEventSubscriber \n public once(): FastEventSubscriber{\n return this.on(arguments[0],arguments[1],Object.assign({},arguments[2],{count:1}))\n }\n\n onAny<P=any>(listener: FastEventListener<Types,P,Meta>, options?:FastEventListenOptions): FastEventSubscriber {\n const type = this.prefix + '**'\n return this.on(type as any,listener,options)\n } \n offAll(){\n this.emitter.offAll(this.prefix)\n } \n off(listener: FastEventListener<any, any,any>):void \n off(type: string, listener: FastEventListener<any, any, any>):void\n off(type: Types, listener: FastEventListener<any, any, any>):void\n off(type: string):void\n off(type: Types):void\n off(){\n const args = arguments as unknown as [any,any]\n if(typeof(args[0])==='string'){\n args[0] = this._getScopeType(args[0])\n }\n this.emitter.off(...args)\n } \n clear(){\n this.offAll()\n }\n public emit<R=any>(type:string,payload?:any,retain?:boolean):R[]\n public emit<R=any>(type:Types,payload?:Events[Types],retain?:boolean):R[]\n public emit<R=any>():R[]{\n const type = arguments[0] as string\n const payload = arguments[1] \n const retain = arguments[2] as boolean\n return this.emitter.emit(this._getScopeType(type)!,payload,retain)\n }\n public waitFor<R=any>(type:string,timeout?:number):Promise<R>\n public waitFor<R=any>(type:Types,timeout?:number):Promise<R>\n public waitFor<R=any>():Promise<R>{\n const type = arguments[0] as string\n const timeout = arguments[1] as number\n return this.emitter.waitFor(this._getScopeType(type)!,timeout)\n }\n public scope(prefix:string){\n return this.emitter.scope(this._getScopeType(prefix)!)\n }\n}","\n/**\n * \n * 判断path是否与pattern匹配\n * \n * isPathMatched(\"a.b.c\",\"a.b.c\") == true\n * isPathMatched(\"a.b.c\",\"a.b.*\") == true\n * isPathMatched(\"a.b.c\",\"a.*.*\") == true\n * isPathMatched(\"a.b.c\",\"*.*.*\") == true\n * isPathMatched(\"a.b.c\",\".b.*\") == true\n * isPathMatched(\"a.b.c.d\",\"a.**\") == true\n * \n * - '**' 匹配后续的\n * - '*' 匹配任意数量的字符,包括零个字符\n * \n * @param path \n * @param pattern \n */\nexport function isPathMatched(path:string[],pattern:string[]):boolean{\n if(path.length !== pattern.length && (path.length>0 && pattern[pattern.length-1]!=='**') ){\n return false;\n }\n let fPattern = [...pattern]\n if(pattern.length >0 && pattern[pattern.length-1] === '**'){\n fPattern.splice(pattern.length-1,1,...Array.from<string>({\n length: path.length-pattern.length+1\n }).fill('*'))\n }\n for(let i=0;i<path.length;i++){\n if(fPattern[i]==='*'){\n continue\n }\n if(fPattern[i]!==path[i]){\n return false\n }\n }\n return true\n}\n\n ","\n\nexport function removeItem(arr:any[],condition:(item:any)=>boolean){\n let index:number[] = []\n while (true) {\n const i = arr.findIndex((item)=>{ \n return condition(item)\n })\n if(i === -1) {\n index.push(i)\n break\n } \n arr.splice(i,1)\n }\n return index\n}","import { FastEventScope } from './scope';\nimport { \n FastEventListener, \n FastEventOptions, \n FastEvents, \n FastListeners, \n FastListenerNode, \n FastEventSubscriber, \n ScopeEvents,\n FastEventMeta,\n FastEventListenOptions\n} from './types'; \nimport { isPathMatched } from './utils/isPathMatched';\nimport { removeItem } from './utils/removeItem';\n \nexport class FastEvent<\n Events extends FastEvents = FastEvents, \n Types extends keyof Events = keyof Events,\n Meta = unknown\n>{\n public listeners : FastListeners = { __listeners: [] } as unknown as FastListeners\n private _options : FastEventOptions\n private _delimiter : string = '/'\n private _context : any\n private _retainedEvents : Map<string,any> = new Map<string,any>() \n constructor(options?:FastEventOptions<Meta>) { \n this._options = Object.assign({\n delimiter : '/',\n context : null,\n ignoreErrors : true\n }, options)\n this._delimiter = this._options.delimiter!\n this._context = this._options.context || this\n }\n get options(){ return this._options }\n private _addListener(parts:string[],listener:FastEventListener<any,any>,options:Required<FastEventListenOptions>):FastListenerNode | undefined{\n const { count, prepend } = options\n return this._forEachNodes(parts,(node)=>{\n const newListener = count >0 ? [listener,count]: listener as any\n if(prepend){\n node.__listeners.splice(0,0,newListener)\n }else{\n node.__listeners.push(newListener)\n } \n if(typeof(this._options.onAddListener)==='function'){\n this._options.onAddListener(parts,listener)\n }\n }) \n }\n /**\n * \n * 根据parts路径遍历侦听器树,并在最后的节点上执行回调函数\n * \n * @param parts \n * @param callback \n * @returns \n */\n private _forEachNodes(parts:string[],callback:(node:FastListenerNode,parent:FastListenerNode)=>void):FastListenerNode | undefined{\n if(parts.length === 0) return \n let current = this.listeners\n for(let i=0;i<parts.length;i++){\n const part = parts[i]\n if(!(part in current)){\n current[part] = {\n __listeners: []\n } as unknown as FastListeners\n }\n if(i===parts.length-1){ \n const node = current[part]\n callback(node,current)\n return node\n }else{ \n current = current[part]\n }\n }\n return undefined\n } \n\n\n /**\n * 从监听器节点中移除指定的事件监听器\n * @private\n * @param node - 监听器节点\n * @param listener - 需要移除的事件监听器\n * @description 遍历节点的监听器列表,移除所有匹配的监听器。支持移除普通函数和数组形式的监听器\n */\n private _removeListener(node: FastListenerNode, path:string[],listener: FastEventListener<any,any,any>): void {\n if(!listener) return \n removeItem(node.__listeners,(item:any)=>{\n item = Array.isArray(item) ? item[0] : item \n const isRemove = item === listener \n if(isRemove && typeof(this._options.onRemoveListener)==='function'){\n this._options.onRemoveListener(path,listener)\n }\n return isRemove\n }) \n }\n public on<T extends string>(type: T, listener: FastEventListener<T,Events[T],Meta>, options?:FastEventListenOptions ): FastEventSubscriber\n public on<T extends Types=Types>(type: T, listener: FastEventListener<Types,Events[T],Meta>, options?:FastEventListenOptions): FastEventSubscriber\n public on<P=any>(type: '**', listener: FastEventListener<Types,P,Meta>): FastEventSubscriber\n public on(): FastEventSubscriber{\n const type = arguments[0] as string\n const listener = arguments[1] as FastEventListener \n const options = Object.assign({\n count : 0,\n prepend: false\n },arguments[2]) as Required<FastEventListenOptions>\n\n if(type.length===0) throw new Error('event type cannot be empty')\n\n if(type==='**'){\n return this.onAny(listener)\n }\n\n const parts = type.split(this._delimiter);\n const node = this._addListener(parts,listener,options)\n \n // Retain不支持通配符\n if(node && !type.includes('*')) this._emitForLastEvent(type) \n\n return {\n off: ()=>node && this._removeListener(node,parts,listener)\n }\n } \n\n public once<T extends string>(type: T, listener: FastEventListener<T,Events[T],Meta> ): FastEventSubscriber\n public once<T extends Types=Types>(type: T, listener: FastEventListener<Types,Events[T],Meta> ): FastEventSubscriber\n public once(): FastEventSubscriber{\n return this.on(arguments[0],arguments[1],{count:1})\n }\n\n /**\n * 注册一个监听器,用于监听所有事件\n * @param listener 事件监听器函数,可以接收任意类型的事件数据\n * @returns {FastEventSubscriber} 返回一个订阅者对象,包含 off 方法用于取消监听\n * @example\n * ```ts\n * const subscriber = emitter.onAny((eventName, data) => {\n * console.log(eventName, data);\n * });\n * \n * // 取消监听\n * subscriber.off();\n * ```\n */\n onAny<P=any>(listener: FastEventListener<string,P,Meta>, options?:Pick<FastEventListenOptions,'prepend'>): FastEventSubscriber {\n const listeners = this.listeners.__listeners\n if(options && options.prepend){\n listeners.splice(0,0,listener)\n }else{\n listeners.push(listener)\n } \n return {\n off:()=>this._removeListener(this.listeners,[],listener)\n }\n }\n\n off(listener: FastEventListener<any, any, any>):void \n off(type: string, listener: FastEventListener<any, any, any>):void\n off(type: Types, listener: FastEventListener<any, any, any>):void\n off(type: string):void\n off(type: Types):void\n off(){\n const args = arguments\n const type = typeof(args[0])==='function' ? undefined : args[0]\n const listener = typeof(args[0])==='function' ? args[0] : args[1]\n const parts = type ? type.split(this._delimiter) : []\n const hasWildcard= type ? type.includes('*') : false\n if(type && !hasWildcard){\n this._traverseToPath(this.listeners,parts,(node)=>{\n if(listener){ // 只删除指定的监听器\n this._removeListener(node,parts,listener)\n }else if(type){\n node.__listeners=[]\n }\n })\n }else{ // 仅删除指定的侦听器\n const entryParts:string[] = hasWildcard ? [] : parts\n this._traverseListeners(this.listeners,entryParts,(path,node)=>{ \n if(listener!==undefined || (hasWildcard && isPathMatched(path,parts))){\n if(listener){\n this._removeListener(node,parts,listener)\n }else{\n node.__listeners=[]\n } \n }\n })\n }\n }\n \n /**\n * 移除所有事件监听器\n * @param entry - 可选的事件前缀,如果提供则只移除指定前缀下的的监听器\n * @description \n * - 如果提供了prefix参数,则只清除该前缀下的所有监听器\n * - 如果没有提供prefix,则清除所有监听器\n * - 同时会清空保留的事件(_retainedEvents)\n * - 重置监听器对象为空\n\n * @example\n * \n * ```ts\n * emitter.offAll(); // 清除所有监听器\n * emitter.offAll('a/b'); // 清除a/b下的所有监听器\n * \n */\n offAll(entry?: string) { \n if(entry){\n const entryNode = this._getListenerNode(entry.split(this._delimiter))\n if(entryNode) entryNode.__listeners = []\n this._removeRetainedEvents(entry)\n }else{ \n this._retainedEvents.clear() \n this.listeners = { __listeners: [] } as unknown as FastListeners\n }\n }\n\n private _getListenerNode(parts:string[]):FastListenerNode | undefined{\n let entryNode: FastListenerNode | undefined\n this._forEachNodes(parts,(node)=>{\n entryNode = node\n })\n return entryNode\n }\n /**\n * 移除保留的事件\n * @param prefix - 事件前缀。如果不提供,将清除所有保留的事件。\n * 如果提供前缀,将删除所有以该前缀开头的事件。\n * 如果前缀不以分隔符结尾,会自动添加分隔符。\n * @private\n */\n private _removeRetainedEvents(prefix?: string) {\n if (!prefix) this._retainedEvents.clear()\n if(prefix?.endsWith(this._delimiter)){\n prefix+=this._delimiter\n } \n this._retainedEvents.delete(prefix!)\n for(let key of this._retainedEvents.keys()){\n if(key.startsWith(prefix!)){\n this._retainedEvents.delete(key)\n }\n }\n } \n clear(){\n this.offAll()\n }\n private _getMeta(extra:Record<string,any>){\n if(!this._options.meta) return extra\n return Object.assign({},this._options.meta,extra) as FastEventMeta<any,any> \n }\n private _emitForLastEvent(type:string){ \n if(this._retainedEvents.has(type)){\n const payload = this._retainedEvents.get(type)\n const parts = type.split(this._delimiter); \n this._traverseToPath(this.listeners,parts,(node)=>{ \n this._executeListeners(node,payload,this._getMeta({type}))\n }) \n // onAny侦听器保存在根节点中,所以需要执行\n this._executeListeners(this.listeners,payload,this._getMeta({type}))\n } \n }\n\n /**\n * 遍历监听器节点树\n * @param node 当前遍历的监听器节点\n * @param parts 事件名称按'.'分割的部分数组\n * @param callback 遍历到目标节点时的回调函数\n * @param index 当前遍历的parts数组索引,默认为0\n * @param lastFollowing 当命中**时该值为true, 注意**只能作在路径的最后面,如a.**有效,而a.**.b无效\n * @private\n * \n * 支持三种匹配模式:\n * - 精确匹配: 'a.b.c'\n * - 单层通配: 'a.*.c' \n * - 多层通配: 'a.**'\n */\n private _traverseToPath(node: FastListenerNode, parts: string[], callback: (node: FastListenerNode) => void, index: number = 0, lastFollowing?:boolean): void {\n\n if (index >= parts.length) {\n callback(node)\n return\n } \n const part = parts[index] \n\n if(lastFollowing===true){\n this._traverseToPath(node, parts, callback, index + 1,true)\n return\n }\n\n if ('*' in node) {\n this._traverseToPath(node['*'], parts, callback, index + 1)\n } \n // \n if ('**' in node) {\n this._traverseToPath(node['**'], parts, callback, index + 1,true)\n }\n\n if (part in node) {\n this._traverseToPath(node[part], parts, callback, index + 1)\n }\n }\n\n private _traverseListeners(node: FastListenerNode, entry:string[], callback: (path:string[],node: FastListenerNode) => void): void {\n let entryNode: FastListenerNode = node\n // 如果指定了entry路径,则按照路径遍历\n if (entry && entry.length > 0) { \n this._traverseToPath(node, entry,(node)=>{\n entryNode= node\n });\n }\n const traverseNodes = (node: FastListenerNode, callback: (path:string[],node: FastListenerNode) => void,parentPath:string[])=>{\n callback(parentPath, node); \n for(let [key,childNode] of Object.entries(node)){\n if(key.startsWith(\"__\")) continue\n if(childNode){\n traverseNodes(childNode as FastListenerNode, callback,[...parentPath,key]);\n }\n }\n }\n // 如果没有指定entry或entry为空数组,则递归遍历所有节点\n traverseNodes(entryNode, callback,[]);\n } \n\n private _executeListener(listener:any, payload: any,meta: FastEventMeta<any,any> ):any{\n try{\n if(typeof(listener.__wrappedListener)==='function'){\n return listener.__wrappedListener.call(this._context,payload,meta)\n }else{\n return listener.call(this._context,payload,meta)\n }\n }catch(e:any){\n e._trigger = meta.type\n if(typeof(this._options.onListenerError)==='function'){\n this._options.onListenerError.call(this,meta.type,e)\n }\n // 如果忽略错误,则返回错误对象\n if(this._options.ignoreErrors){\n return e\n }else{\n throw e\n }\n }\n }\n\n /**\n * 执行监听器节点中的所有监听函数\n * @param node - FastListenerNode类型的监听器节点\n * @param payload - 事件携带的数据\n * @param type - 事件类型\n * @returns 返回所有监听函数的执行结果数组\n * @private\n * \n * @description\n * 遍历执行节点中的所有监听函数:\n * - 对于普通监听器,直接执行并收集结果\n * - 对于带次数限制的监听器(数组形式),执行后递减次数,当次数为0时移除该监听器\n */\n private _executeListeners(node: FastListenerNode, payload: any, meta: Meta): any[] {\n if (!node || !node.__listeners) return []\n let i = 0\n const listeners = node.__listeners\n let result:any[] = []\n while(i<listeners.length){\n const listener = listeners[i]\n if(Array.isArray(listener)){\n result.push(this._executeListener(listener[0],payload,meta)) \n listener[1]-- \n if(listener[1]===0) {\n listeners.splice(i,1)\n i-- // 抵消后面的i++\n }\n }else{\n result.push(this._executeListener(listener,payload,meta)) \n } \n i++ \n }\n return result\n }\n\n public emit<R=any>(type:string,payload?:any,retain?:boolean,meta?:Meta):R[]\n public emit<R=any>(type:Types,payload?:Events[Types],retain?:boolean,meta?:Meta):R[]\n public emit<R=any>():R[]{\n const type = arguments[0] as string\n const payload = arguments[1] as any\n const retain = arguments[2] as boolean\n const meta = (arguments[3] || {}) as Meta\n\n const parts = type.split(this._delimiter); \n if(retain) {\n this._retainedEvents.set(type,payload)\n } \n const results:any[] = [] \n // onAny侦听器保存在根节点中,所以需要执行 \n results.push(...this._executeListeners(this.listeners,payload,this._getMeta({...meta,type})))\n this._traverseToPath(this.listeners,parts,(node)=>{ \n results.push(...this._executeListeners(node,payload,this._getMeta({...meta,type})))\n }) \n return results\n }\n\n public async emitAsync<R=any>(type:string,payload?:any,retain?:boolean,meta?:Meta):Promise<[R|Error][]>\n public async emitAsync<R=any>(type:Types,payload?:Events[Types],retain?:boolean,meta?:Meta):Promise<[R|Error][]>\n public async emitAsync<P=any>():Promise<[P|Error][]>{\n const type = arguments[0] as string\n const payload = arguments[1] as any\n const retain = arguments[2] as boolean\n const meta = (arguments[3] || {}) as Meta\n\n const results = await Promise.allSettled(this.emit<P>(type,payload,retain,this._getMeta({...meta,type})))\n return results.map((result)=>{\n if(result.status==='fulfilled'){\n return result.value\n }else{\n return result.reason\n }\n })\n }\n\n /**\n * 等待指定事件发生\n * \n * @param type \n * @param timeout 超时时间,单位毫秒,默认为 0,表示无限等待\n */\n public waitFor<R=any>(type:string,timeout?:number):Promise<R>\n public waitFor<R=any>(type:Types,timeout?:number):Promise<R>\n public waitFor<R=any>():Promise<R>{\n const type = arguments[0] as string\n const timeout = arguments[1] as number\n return new Promise<R>((resolve,reject)=>{\n let tid:any\n let subscriber:FastEventSubscriber\n const listener = (payload:any)=>{\n clearTimeout(tid)\n subscriber.off() \n resolve(payload) \n }\n if(timeout && timeout>0){\n tid = setTimeout(()=>{\n subscriber && subscriber.off()\n reject(new Error('wait for event<'+ type +'> is timeout'))\n },timeout)\n }\n subscriber = this.on(type,listener) \n }) \n }\n\n /**\n * 创建事件域\n * \n * 注意:\n * \n * 事件域与当前事件对象共享相同的侦听器表\n * 也就是说,如果在事件域中触发事件,当前事件对象也会触发该事件\n * 两者工不是完全隔离的,仅是事件侦听和触发时的事件类型不同而已\n * \n * const emitter = new FastEvent()\n * \n * const scope= emitter.scope(\"a/b\")\n * \n * scope.on(\"x\",()=>{}) == emitter.on(\"a/b/x\",()=>{})\n * scope.emit(\"x\",1) == emitter.emit(\"a/b/x\",1) \n * scope.offAll() == emitter.offAll(\"a/b\")\n * \n */\n scope<T extends string>(prefix:T){ \n return new FastEventScope<ScopeEvents<Events,T>>(this as unknown as FastEvent<ScopeEvents<Events,T>>,prefix)\n }\n\n} "]}
|
|
1
|
+
{"version":3,"sources":["../src/scope.ts","../src/utils/isPathMatched.ts","../src/utils/removeItem.ts","../src/event.ts"],"names":["FastEventScope","constructor","emitter","prefix","length","endsWith","options","delimiter","_getScopeListener","listener","scopePrefix","scopeListener","__name","message","type","startsWith","Object","assign","substring","__wrappedListener","_getScopeType","undefined","on","args","arguments","once","count","onAny","offAll","off","clear","emit","payload","retain","waitFor","timeout","scope","_FastEventScope","isPathMatched","path","pattern","fPattern","splice","Array","from","fill","i","removeItem","arr","condition","index","findIndex","item","push","FastEvent","listeners","__listeners","_options","_delimiter","_context","_retainedEvents","Map","context","ignoreErrors","_addListener","parts","prepend","_forEachNodes","node","newListener","onAddListener","callback","current","part","_removeListener","isArray","isRemove","onRemoveListener","Error","split","includes","_emitForLastEvent","hasWildcard","_traverseToPath","entryParts","_traverseListeners","entry","entryNode","_getListenerNode","_removeRetainedEvents","delete","key","keys","_createMeta","extra","meta","has","get","_executeListeners","lastFollowing","traverseNodes","parentPath","childNode","entries","_executeListener","call","e","_emitter","onListenerError","result","set","results","emitAsync","Promise","allSettled","map","status","value","reason","resolve","reject","tid","subscriber","clearTimeout","setTimeout","_FastEvent"],"mappings":"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","file":"index.mjs","sourcesContent":["import { FastEvent } from \"./event\";\nimport { FastEventListener, FastEventListenOptions, FastEventMessage, FastEvents, FastEventSubscriber } from \"./types\";\n\nexport class FastEventScope<\n Events extends FastEvents = FastEvents,\n Meta extends Record<string, any> = Record<string, any>,\n Types extends keyof Events = keyof Events\n> {\n constructor(public emitter: FastEvent<Events, Meta, Types>, public prefix: string) {\n if (prefix.length > 0 && !prefix.endsWith(emitter.options.delimiter!)) {\n this.prefix = prefix + emitter.options.delimiter\n }\n }\n private _getScopeListener(listener: FastEventListener): FastEventListener {\n const scopePrefix = this.prefix\n if (scopePrefix.length === 0) return listener\n const scopeListener = function (message: FastEventMessage) {\n if (message.type.startsWith(scopePrefix)) {\n return listener(Object.assign({}, message, {\n type: message.type.substring(scopePrefix.length)\n }))\n }\n }\n // 当启用scope时对监听器进行包装\n //@ts-ignore\n listener.__wrappedListener = scopeListener\n return listener\n }\n private _getScopeType(type: string) {\n return type === undefined ? undefined : this.prefix + type\n }\n\n public on<T extends string>(type: T, listener: FastEventListener<T, Events[T], Meta>, options?: FastEventListenOptions): FastEventSubscriber\n public on<T extends Types = Types>(type: T, listener: FastEventListener<T, Events[T], Meta>, options?: FastEventListenOptions): FastEventSubscriber\n public on(type: '**', listener: FastEventListener<any, any, Meta>): FastEventSubscriber\n public on(): FastEventSubscriber {\n const args = [...arguments] as [any, any, any]\n args[0] = this._getScopeType(args[0])\n args[1] = this._getScopeListener(args[1])\n return this.emitter.on(...args)\n }\n\n public once<T extends string>(type: T, listener: FastEventListener<T, Events[T], Meta>, options?: FastEventListenOptions): FastEventSubscriber\n public once<T extends Types = Types>(type: T, listener: FastEventListener<Types, Events[T], Meta>, options?: FastEventListenOptions): FastEventSubscriber\n public once(): FastEventSubscriber {\n return this.on(arguments[0], arguments[1], Object.assign({}, arguments[2], { count: 1 }))\n }\n\n onAny<P = any>(listener: FastEventListener<Types, P, Meta>, options?: FastEventListenOptions): FastEventSubscriber {\n const type = this.prefix + '**'\n return this.on(type as any, listener, options)\n }\n offAll() {\n this.emitter.offAll(this.prefix)\n }\n off(listener: FastEventListener<any, any, any>): void\n off(type: string, listener: FastEventListener<any, any, any>): void\n off(type: Types, listener: FastEventListener<any, any, any>): void\n off(type: string): void\n off(type: Types): void\n off() {\n const args = arguments as unknown as [any, any]\n if (typeof (args[0]) === 'string') {\n args[0] = this._getScopeType(args[0])\n }\n this.emitter.off(...args)\n }\n clear() {\n this.offAll()\n }\n public emit<R = any>(type: string, payload?: any, retain?: boolean): R[]\n public emit<R = any>(type: Types, payload?: Events[Types], retain?: boolean): R[]\n public emit<R = any>(): R[] {\n const type = arguments[0] as string\n const payload = arguments[1]\n const retain = arguments[2] as boolean\n return this.emitter.emit(this._getScopeType(type)!, payload, retain)\n }\n public waitFor<R = any>(type: string, timeout?: number): Promise<R>\n public waitFor<R = any>(type: Types, timeout?: number): Promise<R>\n public waitFor<R = any>(): Promise<R> {\n const type = arguments[0] as string\n const timeout = arguments[1] as number\n return this.emitter.waitFor(this._getScopeType(type)!, timeout)\n }\n public scope(prefix: string) {\n return this.emitter.scope(this._getScopeType(prefix)!)\n }\n}","\n/**\n * \n * 判断path是否与pattern匹配\n * \n * isPathMatched(\"a.b.c\",\"a.b.c\") == true\n * isPathMatched(\"a.b.c\",\"a.b.*\") == true\n * isPathMatched(\"a.b.c\",\"a.*.*\") == true\n * isPathMatched(\"a.b.c\",\"*.*.*\") == true\n * isPathMatched(\"a.b.c\",\".b.*\") == true\n * isPathMatched(\"a.b.c.d\",\"a.**\") == true\n * \n * - '**' 匹配后续的\n * - '*' 匹配任意数量的字符,包括零个字符\n * \n * @param path \n * @param pattern \n */\nexport function isPathMatched(path:string[],pattern:string[]):boolean{\n if(path.length !== pattern.length && (path.length>0 && pattern[pattern.length-1]!=='**') ){\n return false;\n }\n let fPattern = [...pattern]\n if(pattern.length >0 && pattern[pattern.length-1] === '**'){\n fPattern.splice(pattern.length-1,1,...Array.from<string>({\n length: path.length-pattern.length+1\n }).fill('*'))\n }\n for(let i=0;i<path.length;i++){\n if(fPattern[i]==='*'){\n continue\n }\n if(fPattern[i]!==path[i]){\n return false\n }\n }\n return true\n}\n\n ","\n\nexport function removeItem(arr:any[],condition:(item:any)=>boolean){\n let index:number[] = []\n while (true) {\n const i = arr.findIndex((item)=>{ \n return condition(item)\n })\n if(i === -1) {\n index.push(i)\n break\n } \n arr.splice(i,1)\n }\n return index\n}","import { FastEventScope } from './scope';\nimport {\n FastEventListener,\n FastEventOptions,\n FastEvents,\n FastListeners,\n FastListenerNode,\n FastEventSubscriber,\n ScopeEvents,\n FastEventListenOptions,\n FastEventMessage\n} from './types';\nimport { isPathMatched } from './utils/isPathMatched';\nimport { removeItem } from './utils/removeItem';\n\nexport class FastEvent<\n Events extends FastEvents = FastEvents,\n Meta extends Record<string, any> = Record<string, any>,\n Types extends keyof Events = keyof Events\n> {\n public listeners: FastListeners = { __listeners: [] } as unknown as FastListeners\n private _options: FastEventOptions\n private _delimiter: string = '/'\n private _context: any\n private _retainedEvents: Map<string, any> = new Map<string, any>()\n constructor(options?: FastEventOptions<Meta>) {\n this._options = Object.assign({\n delimiter: '/',\n context: null,\n ignoreErrors: true\n }, options)\n this._delimiter = this._options.delimiter!\n this._context = this._options.context || this\n }\n get options() { return this._options }\n private _addListener(parts: string[], listener: FastEventListener<any, any>, options: Required<FastEventListenOptions>): FastListenerNode | undefined {\n const { count, prepend } = options\n return this._forEachNodes(parts, (node) => {\n const newListener = count > 0 ? [listener, count] : listener as any\n if (prepend) {\n node.__listeners.splice(0, 0, newListener)\n } else {\n node.__listeners.push(newListener)\n }\n if (typeof (this._options.onAddListener) === 'function') {\n this._options.onAddListener(parts, listener)\n }\n })\n }\n /**\n * \n * 根据parts路径遍历侦听器树,并在最后的节点上执行回调函数\n * \n * @param parts \n * @param callback \n * @returns \n */\n private _forEachNodes(parts: string[], callback: (node: FastListenerNode, parent: FastListenerNode) => void): FastListenerNode | undefined {\n if (parts.length === 0) return\n let current = this.listeners\n for (let i = 0; i < parts.length; i++) {\n const part = parts[i]\n if (!(part in current)) {\n current[part] = {\n __listeners: []\n } as unknown as FastListeners\n }\n if (i === parts.length - 1) {\n const node = current[part]\n callback(node, current)\n return node\n } else {\n current = current[part]\n }\n }\n return undefined\n }\n\n\n /**\n * 从监听器节点中移除指定的事件监听器\n * @private\n * @param node - 监听器节点\n * @param listener - 需要移除的事件监听器\n * @description 遍历节点的监听器列表,移除所有匹配的监听器。支持移除普通函数和数组形式的监听器\n */\n private _removeListener(node: FastListenerNode, path: string[], listener: FastEventListener<any, any, any>): void {\n if (!listener) return\n removeItem(node.__listeners, (item: any) => {\n item = Array.isArray(item) ? item[0] : item\n const isRemove = item === listener\n if (isRemove && typeof (this._options.onRemoveListener) === 'function') {\n this._options.onRemoveListener(path, listener)\n }\n return isRemove\n })\n }\n public on<T extends string>(type: T, listener: FastEventListener<T, Events[T], Meta>, options?: FastEventListenOptions): FastEventSubscriber\n public on<T extends Types = Types>(type: T, listener: FastEventListener<Types, Events[T], Meta>, options?: FastEventListenOptions): FastEventSubscriber\n public on<P = any>(type: '**', listener: FastEventListener<Types, P, Meta>): FastEventSubscriber\n public on(): FastEventSubscriber {\n const type = arguments[0] as string\n const listener = arguments[1] as FastEventListener\n const options = Object.assign({\n count: 0,\n prepend: false\n }, arguments[2]) as Required<FastEventListenOptions>\n\n if (type.length === 0) throw new Error('event type cannot be empty')\n\n if (type === '**') {\n return this.onAny(listener)\n }\n\n const parts = type.split(this._delimiter);\n const node = this._addListener(parts, listener, options)\n\n // Retain不支持通配符\n if (node && !type.includes('*')) this._emitForLastEvent(type)\n\n return {\n off: () => node && this._removeListener(node, parts, listener)\n }\n }\n\n public once<T extends string>(type: T, listener: FastEventListener<T, Events[T], Meta>): FastEventSubscriber\n public once<T extends Types = Types>(type: T, listener: FastEventListener<Types, Events[T], Meta>): FastEventSubscriber\n public once(): FastEventSubscriber {\n return this.on(arguments[0], arguments[1], { count: 1 })\n }\n\n /**\n * 注册一个监听器,用于监听所有事件\n * @param listener 事件监听器函数,可以接收任意类型的事件数据\n * @returns {FastEventSubscriber} 返回一个订阅者对象,包含 off 方法用于取消监听\n * @example\n * ```ts\n * const subscriber = emitter.onAny((eventName, data) => {\n * console.log(eventName, data);\n * });\n * \n * // 取消监听\n * subscriber.off();\n * ```\n */\n onAny<P = any>(listener: FastEventListener<string, P, Meta>, options?: Pick<FastEventListenOptions, 'prepend'>): FastEventSubscriber {\n const listeners = this.listeners.__listeners\n if (options && options.prepend) {\n listeners.splice(0, 0, listener)\n } else {\n listeners.push(listener)\n }\n return {\n off: () => this._removeListener(this.listeners, [], listener)\n }\n }\n\n off(listener: FastEventListener<any, any, any>): void\n off(type: string, listener: FastEventListener<any, any, any>): void\n off(type: Types, listener: FastEventListener<any, any, any>): void\n off(type: string): void\n off(type: Types): void\n off() {\n const args = arguments\n const type = typeof (args[0]) === 'function' ? undefined : args[0]\n const listener = typeof (args[0]) === 'function' ? args[0] : args[1]\n const parts = type ? type.split(this._delimiter) : []\n const hasWildcard = type ? type.includes('*') : false\n if (type && !hasWildcard) {\n this._traverseToPath(this.listeners, parts, (node) => {\n if (listener) { // 只删除指定的监听器\n this._removeListener(node, parts, listener)\n } else if (type) {\n node.__listeners = []\n }\n })\n } else { // 仅删除指定的侦听器\n const entryParts: string[] = hasWildcard ? [] : parts\n this._traverseListeners(this.listeners, entryParts, (path, node) => {\n if (listener !== undefined || (hasWildcard && isPathMatched(path, parts))) {\n if (listener) {\n this._removeListener(node, parts, listener)\n } else {\n node.__listeners = []\n }\n }\n })\n }\n }\n\n /**\n * 移除所有事件监听器\n * @param entry - 可选的事件前缀,如果提供则只移除指定前缀下的的监听器\n * @description \n * - 如果提供了prefix参数,则只清除该前缀下的所有监听器\n * - 如果没有提供prefix,则清除所有监听器\n * - 同时会清空保留的事件(_retainedEvents)\n * - 重置监听器对象为空\n\n * @example\n * \n * ```ts\n * emitter.offAll(); // 清除所有监听器\n * emitter.offAll('a/b'); // 清除a/b下的所有监听器\n * \n */\n offAll(entry?: string) {\n if (entry) {\n const entryNode = this._getListenerNode(entry.split(this._delimiter))\n if (entryNode) entryNode.__listeners = []\n this._removeRetainedEvents(entry)\n } else {\n this._retainedEvents.clear()\n this.listeners = { __listeners: [] } as unknown as FastListeners\n }\n }\n\n private _getListenerNode(parts: string[]): FastListenerNode | undefined {\n let entryNode: FastListenerNode | undefined\n this._forEachNodes(parts, (node) => {\n entryNode = node\n })\n return entryNode\n }\n /**\n * 移除保留的事件\n * @param prefix - 事件前缀。如果不提供,将清除所有保留的事件。\n * 如果提供前缀,将删除所有以该前缀开头的事件。\n * 如果前缀不以分隔符结尾,会自动添加分隔符。\n * @private\n */\n private _removeRetainedEvents(prefix?: string) {\n if (!prefix) this._retainedEvents.clear()\n if (prefix?.endsWith(this._delimiter)) {\n prefix += this._delimiter\n }\n this._retainedEvents.delete(prefix!)\n for (let key of this._retainedEvents.keys()) {\n if (key.startsWith(prefix!)) {\n this._retainedEvents.delete(key)\n }\n }\n }\n clear() {\n this.offAll()\n }\n\n private _createMeta(extra: Record<string, any> | undefined) {\n if (!this._options.meta) return extra\n return Object.assign({}, this._options.meta, extra)\n }\n\n\n private _emitForLastEvent(type: string) {\n if (this._retainedEvents.has(type)) {\n const message = this._retainedEvents.get(type)\n const parts = type.split(this._delimiter);\n this._traverseToPath(this.listeners, parts, (node) => {\n this._executeListeners(node, message)\n })\n // onAny侦听器保存在根节点中,所以需要执行\n this._executeListeners(this.listeners, message)\n }\n }\n\n /**\n * 遍历监听器节点树\n * @param node 当前遍历的监听器节点\n * @param parts 事件名称按'.'分割的部分数组\n * @param callback 遍历到目标节点时的回调函数\n * @param index 当前遍历的parts数组索引,默认为0\n * @param lastFollowing 当命中**时该值为true, 注意**只能作在路径的最后面,如a.**有效,而a.**.b无效\n * @private\n * \n * 支持三种匹配模式:\n * - 精确匹配: 'a.b.c'\n * - 单层通配: 'a.*.c' \n * - 多层通配: 'a.**'\n */\n private _traverseToPath(node: FastListenerNode, parts: string[], callback: (node: FastListenerNode) => void, index: number = 0, lastFollowing?: boolean): void {\n\n if (index >= parts.length) {\n callback(node)\n return\n }\n const part = parts[index]\n\n if (lastFollowing === true) {\n this._traverseToPath(node, parts, callback, index + 1, true)\n return\n }\n\n if ('*' in node) {\n this._traverseToPath(node['*'], parts, callback, index + 1)\n }\n // \n if ('**' in node) {\n this._traverseToPath(node['**'], parts, callback, index + 1, true)\n }\n\n if (part in node) {\n this._traverseToPath(node[part], parts, callback, index + 1)\n }\n }\n\n private _traverseListeners(node: FastListenerNode, entry: string[], callback: (path: string[], node: FastListenerNode) => void): void {\n let entryNode: FastListenerNode = node\n // 如果指定了entry路径,则按照路径遍历\n if (entry && entry.length > 0) {\n this._traverseToPath(node, entry, (node) => {\n entryNode = node\n });\n }\n const traverseNodes = (node: FastListenerNode, callback: (path: string[], node: FastListenerNode) => void, parentPath: string[]) => {\n callback(parentPath, node);\n for (let [key, childNode] of Object.entries(node)) {\n if (key.startsWith(\"__\")) continue\n if (childNode) {\n traverseNodes(childNode as FastListenerNode, callback, [...parentPath, key]);\n }\n }\n }\n // 如果没有指定entry或entry为空数组,则递归遍历所有节点\n traverseNodes(entryNode, callback, []);\n }\n\n private _executeListener(listener: any, message: FastEventMessage): any {\n try {\n if (typeof (listener.__wrappedListener) === 'function') {\n return listener.__wrappedListener.call(this._context, message)\n } else {\n return listener.call(this._context, message)\n }\n } catch (e: any) {\n e._emitter = message.type\n if (typeof (this._options.onListenerError) === 'function') {\n this._options.onListenerError.call(this, message.type, e)\n }\n // 如果忽略错误,则返回错误对象\n if (this._options.ignoreErrors) {\n return e\n } else {\n throw e\n }\n }\n }\n\n /**\n * 执行监听器节点中的所有监听函数\n * @param node - FastListenerNode类型的监听器节点\n * @param payload - 事件携带的数据\n * @param type - 事件类型\n * @returns 返回所有监听函数的执行结果数组\n * @private\n * \n * @description\n * 遍历执行节点中的所有监听函数:\n * - 对于普通监听器,直接执行并收集结果\n * - 对于带次数限制的监听器(数组形式),执行后递减次数,当次数为0时移除该监听器\n */\n private _executeListeners(node: FastListenerNode, message: FastEventMessage): any[] {\n if (!node || !node.__listeners) return []\n let i = 0\n const listeners = node.__listeners\n let result: any[] = []\n while (i < listeners.length) {\n const listener = listeners[i]\n if (Array.isArray(listener)) {\n result.push(this._executeListener(listener[0], message))\n listener[1]--\n if (listener[1] === 0) {\n listeners.splice(i, 1)\n i-- // 抵消后面的i++\n }\n } else {\n result.push(this._executeListener(listener, message))\n }\n i++\n }\n return result\n }\n /**\n * 触发事件并执行对应的监听器\n * \n * @param type - 事件类型字符串或包含事件信息的对象\n * @param payload - 事件携带的数据负载\n * @param retain - 是否保留该事件(用于新订阅者)\n * @param meta - 事件元数据\n * @returns 所有监听器的执行结果数组\n * \n * @example\n * // 方式1: 参数形式\n * emit('user.login', { id: 1 }, true)\n * \n * // 方式2: 对象形式\n * emit({ type: 'user.login', payload: { id: 1 } ,meta:{...}}}, true)\n */\n public emit<R = any>(type: string, payload?: any, retain?: boolean, meta?: Meta): R[]\n public emit<R = any>(type: Types, payload?: Events[Types], retain?: boolean, meta?: Meta): R[]\n public emit<R = any>(message: FastEventMessage<Types, Events[Types], Meta>, retain?: boolean): R[]\n public emit<R = any>(message: FastEventMessage<string, any, Meta>, retain?: boolean): R[]\n\n public emit<R = any>(): R[] {\n let type: string, payload: any, retain: boolean, meta: any\n if (typeof (arguments[0]) === 'object') {\n type = arguments[0].type as string\n payload = arguments[0].payload as any\n meta = this._createMeta(arguments[0].meta) as Meta\n retain = arguments[1] as boolean\n } else {\n type = arguments[0] as string\n payload = arguments[1] as any\n retain = arguments[2] as boolean\n meta = this._createMeta(arguments[3])\n }\n const message: FastEventMessage = {\n type,\n payload,\n meta\n }\n const parts = type.split(this._delimiter);\n if (retain) {\n this._retainedEvents.set(type, message)\n }\n const results: any[] = []\n // onAny侦听器保存在根节点中,所以需要执行 \n results.push(...this._executeListeners(this.listeners, message))\n this._traverseToPath(this.listeners, parts, (node) => {\n results.push(...this._executeListeners(node, message))\n })\n return results\n }\n\n public async emitAsync<R = any>(type: string, payload?: any, retain?: boolean, meta?: Meta): Promise<[R | Error][]>\n public async emitAsync<R = any>(type: Types, payload?: Events[Types], retain?: boolean, meta?: Meta): Promise<[R | Error][]>\n public async emitAsync<P = any>(): Promise<[P | Error][]> {\n const type = arguments[0] as string\n const payload = arguments[1] as any\n const retain = arguments[2] as boolean\n const meta = this._createMeta((arguments[3])) as Meta\n const message = {\n type,\n payload,\n meta\n }\n const results = await Promise.allSettled(this.emit<P>(message, retain))\n return results.map((result) => {\n if (result.status === 'fulfilled') {\n return result.value\n } else {\n return result.reason\n }\n })\n }\n\n /**\n * 等待指定事件发生 \n * \n * @param type \n * @param timeout 超时时间,单位毫秒,默认为 0,表示无限等待\n */\n public waitFor<R = any>(type: string, timeout?: number): Promise<R>\n public waitFor<R = any>(type: Types, timeout?: number): Promise<R>\n public waitFor<R = any>(): Promise<R> {\n const type = arguments[0] as string\n const timeout = arguments[1] as number\n return new Promise<R>((resolve, reject) => {\n let tid: any\n let subscriber: FastEventSubscriber\n const listener = (message: any) => {\n clearTimeout(tid)\n subscriber.off()\n resolve(message)\n }\n if (timeout && timeout > 0) {\n tid = setTimeout(() => {\n subscriber && subscriber.off()\n reject(new Error('wait for event<' + type + '> is timeout'))\n }, timeout)\n }\n subscriber = this.on(type, listener)\n })\n }\n\n /**\n * 创建事件域\n * \n * 注意:\n * \n * 事件域与当前事件对象共享相同的侦听器表\n * 也就是说,如果在事件域中触发事件,当前事件对象也会触发该事件\n * 两者工不是完全隔离的,仅是事件侦听和触发时的事件类型不同而已\n * \n * const emitter = new FastEvent()\n * \n * const scope= emitter.scope(\"a/b\")\n * \n * scope.on(\"x\",()=>{}) == emitter.on(\"a/b/x\",()=>{})\n * scope.emit(\"x\",1) == emitter.emit(\"a/b/x\",1) \n * scope.offAll() == emitter.offAll(\"a/b\")\n * \n */\n scope<T extends string>(prefix: T) {\n return new FastEventScope<ScopeEvents<Events, T>>(this as unknown as FastEvent<ScopeEvents<Events, T>>, prefix)\n }\n\n} "]}
|
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -4,9 +4,9 @@ FastEvent is a powerful TypeScript event management library that provides flexib
|
|
|
4
4
|
|
|
5
5
|
Compared to `EventEmitter2`, `FastEvent` has the following advantages:
|
|
6
6
|
|
|
7
|
-
-
|
|
8
|
-
-
|
|
9
|
-
-
|
|
7
|
+
- `FastEvent` performs about `1+` times better than `EventEmitter2` when publishing and subscribing with wildcards.
|
|
8
|
+
- `FastEvent` has a package size of `6.3kb`, while `EventEmitter2` is `43.4kb`.
|
|
9
|
+
- `FastEvent` offers more comprehensive features.
|
|
10
10
|
|
|
11
11
|
# Installation
|
|
12
12
|
|
|
@@ -33,43 +33,67 @@ import { FastEvent } from 'fastevent';
|
|
|
33
33
|
const events = new FastEvent();
|
|
34
34
|
|
|
35
35
|
// Subscribe to event
|
|
36
|
-
events.on('user/login', (
|
|
37
|
-
|
|
36
|
+
events.on('user/login', (message) => {
|
|
37
|
+
console.log('User login:', message.payload);
|
|
38
|
+
console.log('Event type:', message.type);
|
|
39
|
+
console.log('Metadata:', message.meta);
|
|
38
40
|
});
|
|
39
41
|
|
|
40
|
-
// Publish event
|
|
42
|
+
// Publish event - Method 1: Parameters
|
|
41
43
|
events.emit('user/login', { id: 1, name: 'Alice' });
|
|
44
|
+
|
|
45
|
+
// Publish event - Method 2: Message object
|
|
46
|
+
events.emit({
|
|
47
|
+
type: 'user/login',
|
|
48
|
+
payload: { id: 1, name: 'Alice' },
|
|
49
|
+
meta: { timestamp: Date.now() },
|
|
50
|
+
});
|
|
42
51
|
```
|
|
43
52
|
|
|
44
53
|
# Guide
|
|
45
54
|
|
|
55
|
+
## Event Message Format
|
|
56
|
+
|
|
57
|
+
FastEvent uses a standardized message format for all events:
|
|
58
|
+
|
|
59
|
+
```typescript
|
|
60
|
+
type FastEventMessage<T = string, P = any, M = unknown> = {
|
|
61
|
+
type: T; // Event type
|
|
62
|
+
payload: P; // Event data
|
|
63
|
+
meta: M; // Event metadata
|
|
64
|
+
};
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Event listeners always receive this message object, providing consistent access to event data and metadata.
|
|
68
|
+
|
|
46
69
|
## Event Wildcards
|
|
47
70
|
|
|
48
71
|
FastEvent supports two types of wildcards:
|
|
49
|
-
|
|
50
|
-
-
|
|
72
|
+
|
|
73
|
+
- `*`: Matches a single path level
|
|
74
|
+
- `**`: Matches multiple path levels
|
|
51
75
|
|
|
52
76
|
```typescript
|
|
53
77
|
const events = new FastEvent();
|
|
54
78
|
|
|
55
79
|
// Matches user/*/login
|
|
56
|
-
events.on('user/*/login', (
|
|
57
|
-
|
|
80
|
+
events.on('user/*/login', (message) => {
|
|
81
|
+
console.log('Any user type login:', message.payload);
|
|
58
82
|
});
|
|
59
83
|
|
|
60
84
|
// Matches all events under user
|
|
61
|
-
events.on('user/**', (
|
|
62
|
-
|
|
85
|
+
events.on('user/**', (message) => {
|
|
86
|
+
console.log('All user-related events:', message.payload);
|
|
63
87
|
});
|
|
64
88
|
|
|
65
89
|
// Trigger events
|
|
66
|
-
events.emit('user/admin/login', { id: 1 });
|
|
67
|
-
events.emit('user/admin/profile/update', { name: 'New' });
|
|
90
|
+
events.emit('user/admin/login', { id: 1 }); // Both handlers will be called
|
|
91
|
+
events.emit('user/admin/profile/update', { name: 'New' }); // Only ** handler will be called
|
|
68
92
|
```
|
|
69
93
|
|
|
70
94
|
## Event Scoping
|
|
71
95
|
|
|
72
|
-
Scopes allow you to handle events within specific namespaces:
|
|
96
|
+
Scopes allow you to handle events within specific namespaces. Note that scopes share the same listener table with the parent emitter:
|
|
73
97
|
|
|
74
98
|
```typescript
|
|
75
99
|
const events = new FastEvent();
|
|
@@ -77,13 +101,59 @@ const events = new FastEvent();
|
|
|
77
101
|
// Create user-related scope
|
|
78
102
|
const userScope = events.scope('user');
|
|
79
103
|
|
|
80
|
-
//
|
|
81
|
-
userScope.on('login',
|
|
82
|
-
|
|
83
|
-
|
|
104
|
+
// These are equivalent:
|
|
105
|
+
userScope.on('login', handler);
|
|
106
|
+
events.on('user/login', handler);
|
|
107
|
+
|
|
108
|
+
// These are also equivalent:
|
|
109
|
+
userScope.emit('login', data);
|
|
110
|
+
events.emit('user/login', data);
|
|
111
|
+
|
|
112
|
+
// Clear all listeners in the scope
|
|
113
|
+
userScope.offAll(); // Equivalent to events.offAll('user')
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
## Listener Options
|
|
117
|
+
|
|
118
|
+
When subscribing to events, you can specify additional options:
|
|
119
|
+
|
|
120
|
+
```typescript
|
|
121
|
+
interface FastEventListenOptions {
|
|
122
|
+
// Number of times the listener should be called (0 for unlimited, 1 for once)
|
|
123
|
+
count?: number;
|
|
124
|
+
// Add the listener to the beginning of the listeners array
|
|
125
|
+
prepend?: boolean;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Example: Listen for first 3 occurrences
|
|
129
|
+
events.on('data', handler, { count: 3 });
|
|
130
|
+
|
|
131
|
+
// Example: Ensure handler is called before other listeners
|
|
132
|
+
events.on('important', handler, { prepend: true });
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## Removing Listeners
|
|
136
|
+
|
|
137
|
+
FastEvent provides multiple ways to remove listeners:
|
|
138
|
+
|
|
139
|
+
```typescript
|
|
140
|
+
// Remove specific listener
|
|
141
|
+
events.off(listener);
|
|
142
|
+
|
|
143
|
+
// Remove all listeners for an event
|
|
144
|
+
events.off('user/login');
|
|
145
|
+
|
|
146
|
+
// Remove specific listener for an event
|
|
147
|
+
events.off('user/login', listener);
|
|
148
|
+
|
|
149
|
+
// Remove all listeners with wildcard pattern
|
|
150
|
+
events.off('user/*');
|
|
151
|
+
|
|
152
|
+
// Remove all listeners
|
|
153
|
+
events.offAll();
|
|
84
154
|
|
|
85
|
-
//
|
|
86
|
-
|
|
155
|
+
// Remove all listeners under a prefix
|
|
156
|
+
events.offAll('user');
|
|
87
157
|
```
|
|
88
158
|
|
|
89
159
|
## One-time Events
|
|
@@ -94,11 +164,11 @@ Use `once` to subscribe to events that trigger only once:
|
|
|
94
164
|
const events = new FastEvent();
|
|
95
165
|
|
|
96
166
|
events.once('startup', () => {
|
|
97
|
-
|
|
167
|
+
console.log('Application started');
|
|
98
168
|
});
|
|
99
169
|
|
|
100
|
-
|
|
101
|
-
events.
|
|
170
|
+
// Equivalent to:
|
|
171
|
+
events.on('startup', handler, { count: 1 });
|
|
102
172
|
```
|
|
103
173
|
|
|
104
174
|
## Asynchronous Events
|
|
@@ -109,15 +179,42 @@ Support for asynchronous event handling:
|
|
|
109
179
|
const events = new FastEvent();
|
|
110
180
|
|
|
111
181
|
events.on('data/fetch', async () => {
|
|
112
|
-
|
|
113
|
-
|
|
182
|
+
const response = await fetch('https://api.example.com/data');
|
|
183
|
+
return await response.json();
|
|
114
184
|
});
|
|
115
185
|
|
|
116
|
-
// Async event publishing
|
|
186
|
+
// Async event publishing returns array of results/errors
|
|
117
187
|
const results = await events.emitAsync('data/fetch');
|
|
118
188
|
console.log('Results from all handlers:', results);
|
|
119
189
|
```
|
|
120
190
|
|
|
191
|
+
## Listener Return Values
|
|
192
|
+
|
|
193
|
+
Both `emit` and `emitAsync` methods return the results from all event listeners:
|
|
194
|
+
|
|
195
|
+
```typescript
|
|
196
|
+
const events = new FastEvent();
|
|
197
|
+
|
|
198
|
+
// Synchronous listeners with return values
|
|
199
|
+
events.on('calculate', () => 1);
|
|
200
|
+
events.on('calculate', () => 2);
|
|
201
|
+
events.on('calculate', () => 3);
|
|
202
|
+
|
|
203
|
+
// Get array of return values
|
|
204
|
+
const results = events.emit('calculate');
|
|
205
|
+
console.log('Results:', results); // [1, 2, 3]
|
|
206
|
+
|
|
207
|
+
// Asynchronous listeners
|
|
208
|
+
events.on('process', async () => 'result 1');
|
|
209
|
+
events.on('process', async () => 'result 2');
|
|
210
|
+
|
|
211
|
+
// Get array of resolved values/errors
|
|
212
|
+
const asyncResults = await events.emitAsync('process');
|
|
213
|
+
console.log('Async results:', asyncResults); // ['result 1', 'result 2']
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
For asynchronous events, `emitAsync` will wait for all listeners to complete and return an array containing either the resolved values or error objects if a listener fails.
|
|
217
|
+
|
|
121
218
|
## Event Waiting
|
|
122
219
|
|
|
123
220
|
Use `waitFor` to wait for specific events:
|
|
@@ -126,13 +223,13 @@ Use `waitFor` to wait for specific events:
|
|
|
126
223
|
const events = new FastEvent();
|
|
127
224
|
|
|
128
225
|
async function waitForLogin() {
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
226
|
+
try {
|
|
227
|
+
// Wait for login event with 5 seconds timeout
|
|
228
|
+
const userData = await events.waitFor('user/login', 5000);
|
|
229
|
+
console.log('User logged in:', userData);
|
|
230
|
+
} catch (error) {
|
|
231
|
+
console.log('Login wait timeout');
|
|
232
|
+
}
|
|
136
233
|
}
|
|
137
234
|
|
|
138
235
|
waitForLogin();
|
|
@@ -151,8 +248,8 @@ const events = new FastEvent();
|
|
|
151
248
|
events.emit('config/update', { theme: 'dark' }, true);
|
|
152
249
|
|
|
153
250
|
// Later subscribers will immediately receive the retained data
|
|
154
|
-
events.on('config/update', (
|
|
155
|
-
|
|
251
|
+
events.on('config/update', (message) => {
|
|
252
|
+
console.log('Config:', message.payload); // Immediately outputs: Config: { theme: 'dark' }
|
|
156
253
|
});
|
|
157
254
|
```
|
|
158
255
|
|
|
@@ -164,7 +261,7 @@ By default, '/' is used as the event path delimiter, but you can use custom deli
|
|
|
164
261
|
|
|
165
262
|
```typescript
|
|
166
263
|
const events = new FastEvent({
|
|
167
|
-
|
|
264
|
+
delimiter: '.',
|
|
168
265
|
});
|
|
169
266
|
```
|
|
170
267
|
|
|
@@ -175,12 +272,12 @@ Use `onAny` to listen to all events:
|
|
|
175
272
|
```typescript
|
|
176
273
|
const events = new FastEvent();
|
|
177
274
|
|
|
178
|
-
events.onAny((
|
|
179
|
-
|
|
275
|
+
events.onAny((message) => {
|
|
276
|
+
console.log(`Event ${message.type} triggered:`, message.payload);
|
|
180
277
|
});
|
|
181
278
|
|
|
182
|
-
|
|
183
|
-
events.
|
|
279
|
+
// Can also use prepend option
|
|
280
|
+
events.onAny(handler, { prepend: true });
|
|
184
281
|
```
|
|
185
282
|
|
|
186
283
|
## Metadata (Meta)
|
|
@@ -193,15 +290,15 @@ Set global metadata when creating a FastEvent instance:
|
|
|
193
290
|
|
|
194
291
|
```typescript
|
|
195
292
|
const events = new FastEvent({
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
293
|
+
meta: {
|
|
294
|
+
version: '1.0',
|
|
295
|
+
environment: 'production',
|
|
296
|
+
},
|
|
200
297
|
});
|
|
201
298
|
|
|
202
|
-
events.on('user/login', (
|
|
203
|
-
|
|
204
|
-
|
|
299
|
+
events.on('user/login', (message) => {
|
|
300
|
+
console.log('Event data:', message.payload);
|
|
301
|
+
console.log('Metadata:', message.meta); // Contains type, version, and environment
|
|
205
302
|
});
|
|
206
303
|
```
|
|
207
304
|
|
|
@@ -211,20 +308,21 @@ Additional metadata can be passed when publishing events, which will be merged w
|
|
|
211
308
|
|
|
212
309
|
```typescript
|
|
213
310
|
const events = new FastEvent({
|
|
214
|
-
|
|
311
|
+
meta: { app: 'MyApp' },
|
|
215
312
|
});
|
|
216
313
|
|
|
217
314
|
// Add specific metadata when publishing event
|
|
218
|
-
events.emit(
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
315
|
+
events.emit(
|
|
316
|
+
'order/create',
|
|
317
|
+
{ orderId: '123' }, // Event data
|
|
318
|
+
false, // Don't retain
|
|
319
|
+
{ timestamp: Date.now() }, // Event-specific metadata
|
|
222
320
|
);
|
|
223
321
|
|
|
224
322
|
// Listener receives merged metadata
|
|
225
|
-
events.on('order/create', (
|
|
226
|
-
|
|
227
|
-
|
|
323
|
+
events.on('order/create', (message) => {
|
|
324
|
+
console.log('Order:', message.payload); // { orderId: '123' }
|
|
325
|
+
console.log('Metadata:', message.meta); // { type: 'order/create', app: 'MyApp', timestamp: ... }
|
|
228
326
|
});
|
|
229
327
|
```
|
|
230
328
|
|
|
@@ -234,20 +332,47 @@ FastEvent provides error handling mechanisms:
|
|
|
234
332
|
|
|
235
333
|
```typescript
|
|
236
334
|
const events = new FastEvent({
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
335
|
+
ignoreErrors: true, // Default is true, won't throw errors
|
|
336
|
+
onListenerError: (type, error) => {
|
|
337
|
+
console.error(`Error handling event ${type}:`, error);
|
|
338
|
+
},
|
|
241
339
|
});
|
|
242
340
|
|
|
243
341
|
events.on('process', () => {
|
|
244
|
-
|
|
342
|
+
throw new Error('Processing failed');
|
|
245
343
|
});
|
|
246
344
|
|
|
247
345
|
// Won't throw error, will trigger onListenerError instead
|
|
248
346
|
events.emit('process');
|
|
249
347
|
```
|
|
250
348
|
|
|
349
|
+
## TypeScript Support
|
|
350
|
+
|
|
351
|
+
FastEvent is written in TypeScript and provides full type support:
|
|
352
|
+
|
|
353
|
+
```typescript
|
|
354
|
+
// Define event types
|
|
355
|
+
interface MyEvents {
|
|
356
|
+
'user/login': { id: number; name: string };
|
|
357
|
+
'user/logout': { id: number };
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
// Create typed event emitter
|
|
361
|
+
const events = new FastEvent<MyEvents>();
|
|
362
|
+
|
|
363
|
+
// Type checking for event names and payload
|
|
364
|
+
events.on('user/login', (message) => {
|
|
365
|
+
// message.payload is typed as { id: number; name: string }
|
|
366
|
+
const { id, name } = message.payload;
|
|
367
|
+
});
|
|
368
|
+
|
|
369
|
+
// Error: wrong event name
|
|
370
|
+
events.emit('wrong/event', {});
|
|
371
|
+
|
|
372
|
+
// Error: wrong payload type
|
|
373
|
+
events.emit('user/login', { wrong: 'type' });
|
|
374
|
+
```
|
|
375
|
+
|
|
251
376
|
## Custom Options
|
|
252
377
|
|
|
253
378
|
The FastEvent constructor supports multiple options:
|
|
@@ -255,18 +380,18 @@ The FastEvent constructor supports multiple options:
|
|
|
255
380
|
```typescript
|
|
256
381
|
const events = new FastEvent({
|
|
257
382
|
// Event path delimiter, default is '/'
|
|
258
|
-
delimiter: '.',
|
|
383
|
+
delimiter: '.',
|
|
259
384
|
// Context for event handlers
|
|
260
|
-
context: null,
|
|
385
|
+
context: null,
|
|
261
386
|
// Metadata, passed to all event handlers
|
|
262
387
|
meta: { ... },
|
|
263
|
-
|
|
388
|
+
|
|
264
389
|
// Error handling
|
|
265
390
|
ignoreErrors: true,
|
|
266
391
|
onListenerError: (type, error) => {
|
|
267
392
|
console.error(`Event error:`, type, error);
|
|
268
393
|
},
|
|
269
|
-
|
|
394
|
+
|
|
270
395
|
// Callbacks for listener addition/removal
|
|
271
396
|
onAddListener: (path, listener) => {
|
|
272
397
|
console.log('Listener added:', path);
|
|
@@ -279,4 +404,4 @@ const events = new FastEvent({
|
|
|
279
404
|
|
|
280
405
|
# Performance
|
|
281
406
|
|
|
282
|
-

|
|
407
|
+

|