我有一个事件调度程序类,它应该在某些事件发生时触发监听器。我想通过装饰器注册事件监听器 - 这已经有效,但我对当前的解决方案不是 100% 满意。
目前,事件监听器由全局注册表“收集”,然后在事件调度程序中注册。在代码中,我的(简化的)装饰器看起来像:
// Decorator
export const EventListener = (events: string[]) => {
return (target: Type<object>): void => {
EventListenerRegistry.set(target);
};
};
// Listener example
@EventListener(['start'])
class OnStart {
public handle() {
}
}
OnStart
监听器将在 start
事件被调度后立即触发。
我不喜欢这种方法的地方是需要 EventListenerRegistry
,它看起来像:
export const EventListenerRegistry = (new class {
protected listeners = [];
public set(target) {
this.listeners.push(target);
}
});
导入 EventListenerRegistry
意味着在任何时候导入相同的实例,使其非常“单例化”。
我的听众是通过 glob
require
d - 所以这种方法可以自动将我的听众注册到我的调度程序,而无需做任何额外的工作。
但是除了使用(丑陋的)注册表类之外还有其他可能性吗?
最佳答案
我会使用 IoC 容器。一个不错的 TypeScript 是 Inversify . 这将允许这样的事情:
import { injectable, inject } from 'inversify';
enum EventType {
Start,
}
interface IEvent {
type: Event;
handle(): void;
}
@injectable()
class OnStart implements IEvent {
public readonly type = EventType.Start;
public handle() {
}
}
@injectable()
class Application {
public constructor(@multiInject(EVENT) public events: IEvent[]) {
}
}
但这确实意味着您必须自己进行绑定(bind):
export const EVENT = symbol('event');
container.bind<IEvent>(EVENT).to(OnStart);
...
但是,如果您真的想让事件自己自动注册,我想您可以简单地将容器导入装饰器并在那里进行绑定(bind)。
关于typescript - 收集装饰类(没有注册类),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50820746/