; 这个库是同时只发射一个timer,用这个库触发的timer可以保证排队执行 #Persistent ; 确保脚本一直运行,直到我们的timmer被解雇 Hello(words) { Msgbox, % "Hello " words "!" ; 我们需要自己编写退出脚本,使用时 #Persistent ExitApp } emitter := new AEEmitter() emitter.On("say", Func("Hello")) ; 注册事件 ; 消息框将显示“Hello World!” emitter.emit("say", "World") ; 触发它 ; #include <AEE> /* ***************************************************** Author: helsmy Website: https://github.com/helsmy/ahk_AEE Lisence: LGPLv2.1 Plesase redistribute with above information ****************************************************** A simple event driven framework for the most simple way: #Persistent ; Ensure script keeps running until our timmer is fired #include <AEE> Hello(words) { Msgbox, % "Hello " words "!" ; we need exit script by ourselves, ; when use #Persistent ExitApp } emitter := new AEEmitter() emitter.On("say", Func("Hello")) ; register a event ; A msgbox will show with "Hello World!" emitter.emit("say", "World") ; fire it Property: eventsCount(ReadOnly): number of events registered maxListener(ReadOnly): the maximum number of listeners that an event can have Special Event: newListener: fired every times when a new listener is added listener must accept 2 parameters: type: event name of added listener listener: added listener removeListener: fired every times when a listener of a event is removed listener must accept 2 parameters: type: event name of removed listener listener: removed listener. If more than one listener is removed at once, this parameter passes an array containing all reomved listeners. */ class AEEmitter { _events := {} _eventsCount := 0 _maxListener := 10 eventsCount[] { get { return this._eventsCount } set { throw Exception("Set to read only property", -1, "eventsCount") } } maxListener[] { get { return this._maxListener } set { throw Exception("Set to read only property", -1, "maxListener") } } /** * Add a listener to wait for a event * @params: type event name waited * @params: callback listener * @params: prepend If ture, add listener to the head of listener list(will be execute earlier) */ On(type, callback, prepend := false) { return this._AddListener(type, callback, prepend) } /** * Remove a listener waiting for a event * @params: type event name waited * @params: callback listener to be removed */ Off(type, callback) { return this.RemoveListener(type, callback) } /** * Add a listener to wait for a event * This listener will be removed Once it has been executed * @params: type event name waited * @params: callback listener * @params: prepend If ture, add listener to the head of listener list(will be execute earlier) */ Once(type, listener, prepend := false) { return this._AddListener(type, listener, prepend, true) } /** * Add a listener to wait for a event * @params: type event name waited * @params: listener listener * @params: prepend If ture, add listener to the head of listener list(will be execute earlier) */ AddListener(type, listener, prepend := false) { return this._AddListener(type, listener, prepend) } /** * Add a listener in the head of listener list(will be execute earlier) to wait for a event * @params: type event name waited * @params: listener listener */ PrependListener(type, listener) { return this._AddListener(type, listener, true) } /** * Remove a listener waiting for a event * @params: type event name waited * @params: listener listener to be removed */ RemoveListener(type, listener) { events := this._events, list := events[type] for p, l in list { if (l == listener) { list.RemoveAt(p) if (list.Length() == 0) this.RemoveEvent(type) if (events.HasKey("removeListener")) this.Emit("removeListener", type, listener) break } } return this } /** * Remove all listener of a event * @params: type event name waited */ RemoveAllListener(type) { events := this._events if (events.HasKey(type)) listeners := events[type], events[type] := [] if (events.HasKey("removeListener")) this.Emit("removeListener", type, listeners) return this } /** * Remove a event from monitor * @params: type event name to be removed */ RemoveEvent(type) { events := this._events if (events.HasKey(type)) events.Delete(type), --this._eventsCount return this } /** * Emit a specific event * @params: type event name waited * @params: params* params to be passed to each listener */ Emit(type, params*) { if (this._events.HasKey(type)) { for _, handler in this._events[type] { if (handler.Length()) handler := ObjBindMethod(this, "_OnceWapper", type, handler) __AEE_EventDispatcher.Put(handler, params) } } return true } /** * Emit a specific event and execute each listener as quick as possible * @params: type event name waited * @params: params* params to be passed to each listener */ EmitImmediate(type, params*) { if (this._events.HasKey(type)) { for _, handler in this._events[type] { if (handler.Length()) handler := ObjBindMethod(this, "_OnceWapper", type, handler) __AEE_EventDispatcher.Put(handler, params, true) } } return true } /** * Set property maxListener */ SetMaxListener(number) { n := number&-1 if (number != n) throw Exception("Value Error!", -1, "Need an integer.") this._maxListener := n } /** * return number of listeners of a event */ ListenerCount(type) { return this._events.HasKey(type) ? this._events[type].Length() : 0 } /** * return all listeners(in a array) of a event */ Listeners(type) { if (!this._events.HasKey(type)) return [] all_l := [] for _, l in this._events l := IsFunc(l) ? l : l[1] , all_l.Push(l) return all_l } /** * return all events' name(in a array) registered */ EventNames() { names := [] for name in this._events names.Push(name) return names } /* * Inner wapper for `Once` method to remove listener after executed * DO NOT CALL IT */ _OnceWapper(type, fn, params*) { events := this._events, list := events[type] ; Once marked listener is contained in a 1 length array fn[1].Call(params*) this.RemoveListener(type, fn) } /* * Inner method. * DO NOT CALL IT */ _AddListener(type, callback, prepend := false, isOnce := false) { if (!_IsFuncEx(callback)) ; IsFunc does not work on method, sad throw Exception("Value Error", -2, "Listener(callback) must be a function or method") if (!this._events) this._events := {} events := this._events if (events.HasKey("newListener")) this.Emit("newListener", type, callback) if (!events.HasKey(type)) events[type] := [], ++this._eventsCount if (events[type].Length() >= this._maxListener) throw Exception("The number of listeners has reached the maximum.", -2, "Use method SetMaxListener to increase it.") ; mark once by making a non-function callback if (isOnce) callback := [callback] if (!prepend) events[type].Push(callback) else events[type].InsertAt(1, callback) return this } } ; *************** INNER CLASS ******************* ; DO NOT DRICTLY CALL IT ; UNLESS YOU KNOW WHAT YOU ARE DONING ; *********************************************** class __AEE_EventDispatcher { /* * Based on DBGp_DispatchTimer of Lexikos's dbgp.ahk */ static eventQueue := [] static immediateQueue := [] Put(handler, data, immediate := false) { if !immediate this.eventQueue.Push([handler, data]) else this.immediateQueue.Push([handler, data]) ; Using a single timer ensures that each handler finishes before ; the next is called, and that each runs in its own thread. static DT := ObjBindMethod(__AEE_EventDispatcher, "DispatchTimer") SetTimer, % DT, -1 } DispatchTimer() { static DT := ObjBindMethod(__AEE_EventDispatcher, "DispatchTimer") ; Clear immediateQueue array before fire handler of eventQueue if (next := this.immediateQueue.RemoveAt(1)) fn := next[1], %fn%(next[2]*) ; Call exactly one handler per new thread. else if next := this.eventQueue.RemoveAt(1) fn := next[1], %fn%(next[2]*) ; If the queue is not empty, reset the timer. if (this.eventQueue.Length() || this.immediateQueue.Length()) SetTimer, % DT, -1 } } _IsFuncEx(obj) { static nBoundFunc := NumGet(&(f := Func("Func").Bind())) return IsFunc(obj) || (NumGet(&obj) == nBoundFunc) }
声明:站内资源为整理优化好的代码上传分享与学习研究,如果是开源代码基本都会标明出处,方便大家扩展学习路径。请不要恶意搬运,破坏站长辛苦整理维护的劳动成果。本站为爱好者分享站点,所有内容不作为商业行为。如若本站上传内容侵犯了原著者的合法权益,请联系我们进行删除下架。
评论(0)