Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

功能请求:希望增加“事件驱动”注解 #3073

Open
2509989976 opened this issue Jul 10, 2023 · 1 comment
Open

功能请求:希望增加“事件驱动”注解 #3073

2509989976 opened this issue Jul 10, 2023 · 1 comment
Labels
type: enhancement New feature or request

Comments

@2509989976
Copy link

功能请求:希望增加“事件驱动”注解
参考:https://nest.nodejs.cn/techniques/events
具体用途:
例如,在用户注册后,为新用户赠送积分,赠送优惠券,为当前推广人增加推广人数,以及一些临时活动等等操作,如果都写到用户注册相关的service中,不同的业务逻辑代码就会紧紧的耦合在一起。如果新的活动增加和取消,又要更改新的代码。
如果采用事件驱动的方式,只需要在注册后发送一个事件,让其他业务去监听注册事件即可。

伪代码实现如下

//注册业务
@Provide()
export class UserService {
  
  @Inject()
  event
  
  async signup(options: IUserOptions) {
    //注册逻辑。。。略。。。
    event.emit('signup', options);
    //或者
    event.emit('signup',new SignUpEvent(options));
    //又或者
    event.emit(new SignUpEvent(options));
  }
}

//事件业务,其中不同的监听者可能会分布在不同的service中
@Provide()
export class ServiceB {
  
  @EventListener('signup')
  async onSignup(options: any) {
  }
  
  @EventListener('signup')
  async onSignup2(options: SignUpEvent) {
  }
  
  @EventListener(SignUpEvent)
  async onSignup3(options: SignUpEvent) {
  }
}

其他可选选项
1.是否获取事件结果值
2.是异步还是同步
3.监听者遇到错误时事件发布者是否继续执行
4.等等

@czy88840616 czy88840616 added pr: new feature This PR adds a new API or behavior. type: enhancement New feature or request and removed pr: new feature This PR adds a new API or behavior. labels Jul 10, 2023
@im3ott
Copy link

im3ott commented Oct 24, 2023

定义装饰器

import { attachClassMetadata, Provide, saveModule } from "@midwayjs/core";

export const Events = (identifier?: string): ClassDecorator => (target: any) => {
    saveModule("Decorator.EventHandler", target);
    Provide(identifier)(target);
}

export const EventListener = (name: string) => (target: any, propertyName: string) => {
    attachClassMetadata("Decorator.EventListener", { name }, target, propertyName);
};

事件管理器 (Singleton)

import { IMidwayContainer, ApplicationContext, getClassMetadata, listModule, Singleton } from "@midwayjs/core";
import { EventEmitter } from "events";

@Singleton()
export class EventManager extends EventEmitter {

    private readonly _ListenedEvents: Set<string> = new Set();

    @ApplicationContext()
    applicationContext: IMidwayContainer;

    /** 注册事件 */
    async register() {
        let eventHandlers = listModule("Decorator.EventHandler");
        if (!eventHandlers.length) return;
        for (const e of eventHandlers) {
            let metadata = getClassMetadata("Decorator.EventListener", e),
                instance = await this.applicationContext.getAsync(e);
            for (const k in metadata) {
                this.listen(metadata[k].name, e.prototype[k], instance);
            }
        }
    }

    /**
     * 监听事件
     * @param name 事件名
     * @param mode 事件模式
     * @param listener 事件监听器
     * @param source 事件源
     */
    private listen(name: string, listener: EventListener, source?: any) {
        let result = false;
        if (!name || !listener) return;
        // 扩展事件类型,注册模式等
        this.on(name, source ? listener.bind(source) : listener);
        this._ListenedEvents.add(name);
    }

    // 取消监听、清理事件等
}

在 onReady 的时候调用 register 注册事件

@Events()
export class TestService {

    @EventListener("eventName")
    onTesting(arg1: string, arg2: number) {

    }
}

@Provide()
export class EmitterService {

    @Inject()
    private eventManager: EventManager;

    emitEvent() {
        this.eventManager.emit("eventName");
    }
}

不足之处还望各位大佬指教

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: enhancement New feature or request
Development

No branches or pull requests

3 participants