创建了用户之后,会发布一个 UserCreatedEvent 事件,发生了这个事件以后,我希望再执行一个命令,比如给新创建的用户发送一条欢迎信息。这个动作可以在 Saga 里面完成。
先去创建一个新的命令还有对应的命令处理器,在 user,commands 里面,新建一个文件,名字是 send-welcome-message.command.ts
文件里 export 一个 class,SendWelcomeMessageCommand,在类里面添加一个构造方法,里面添加一个参数属性,public readonly 名字是 user,类型暂时设置成 any。
下面在定义一个对应的命令处理器,新建一个文件,名字是 send-welcome-message.command.handler.ts
文件里 export 一个 class,名字是 SendWelcomeMessageCommandHandler,这个类可以 implements 一下 ICommandHandler 接口,类型是 SendWelcomeMessageCommand 。
在类里面添加一个构造方法,在这个构造方法里添加一个参数属性,注入 EventBus 依赖,private readonly eventBus,类型是 EventBus。
类里面,再添加一个 async 方法,名字要设置成 execute,方法接收一个 command 参数,类型是 SendWelcomeMessageCommand ,方法里面,用一个 console.log 在控制台上输出 Welcome ,后面加上 command.user.name。
注册
打开 UserModule 模块,在模块的 providers 里面,添加一个 SendWelcomeMessageCommandHandler 。
Saga
然后打开之前创建的 UserSaga,在这个类里面,再添加一个方法,方法的名字可以是 sendWelcomeMessage ,在这个方法的上面,用 @Saga 装饰器装饰一下。
方法接收一个 events$ ,事件流,类型是 Observable
里面先用一个 ofType 筛选一下要处理的事件的类型,这个 ofType 来自 @nestjs/cqrs。 事件的名字是 UserCreatedEvent。
接着再用一个 map 操作员,它来自 rxjs/operators。 提供一个函数参数,函数有个 event 参数,它的值就是事件流上的事件,这个事件应该是一个 UserCreatedEvent,因为上面已经用 ofType 筛选了一下,所以这个 event 只能是 UserCreatedEvent 事件。
函数 return 的是,新建一个命令,命令是 SendWelcomeMessageCommand,再把 event 里的 user 交给它。
测试
下面再打开 Http 客户端,用 POST 方法带着一个 JSON 格式的数据,请求 users 接口。
回到运行项目开发服务的终端,提示找不到 CommandHandler,这是因为之前定义 SendWelcomeMessageCommandHandler 的时候,忘记在这个类上面,使用 @CommandHandler 装饰器了,添加一个这样的装饰器,然后把这个处理器要处理的事件交给这个装饰器,这里就是 SendWelcomeMessageCommand 。
再回到 Http 客户端,重新发送一下这个请求。
这次在终端这里会输出一条信息: Welcome wanghao。 在客户端用 Http 的 POST 方法请求 users 接口,会执行一个 CreateUser 命令,在命令的处理器那里发布了一个 UserCreated 事件。
我们创建的 sendWelcomeMessage 这个 Saga 会对这个事件做出反应,做的事就是执行了一个 SendWelcomeMessageCommand 事件,这个事件的处理器做的事情,就是在控制台上输出这条信息。