Команда в Nest
Страница должна добавить строку в память, но метод контроллера не должен знать, где именно лежит массив и как устроена запись. Без общей шины каждый новый адрес снова тянет дублирование логики.
Команда
- простой класс с полями,
который описывает намерение
изменить состояние. Сервис
создаёт такой объект и передаёт
его CommandBus,
а Nest находит обработчик
по типу команды. Пакет
@nestjs/cqrs
подключают в корневом модуле
через CqrsModule.forRoot,
иначе шина не появится
в приложении.
Без обработчика команда
никуда не дойдёт: рядом
регистрируют класс с пометкой
@CommandHandler,
который реализует
ICommandHandler
и меняет данные в памяти.
Покажем на примере постов:
import { Module } from '@nestjs/common';
import { CqrsModule } from '@nestjs/cqrs';
import { PostController } from './post.controller.js';
import { CreatePostHandler } from './create-post.handler.js';
import { PostService } from './post.service.js';
@Module({
imports: [CqrsModule.forRoot()],
controllers: [PostController],
providers: [PostService, CreatePostHandler],
})
export class AppModule {}
Класс команды хранит заголовок новой строки:
export class CreatePostCommand {
title: string;
constructor(title: string) {
this.title = title;
}
}
Сервис получает шину через конструктор и передаёт ей команду при создании:
import { Injectable } from '@nestjs/common';
import { CommandBus } from '@nestjs/cqrs';
import { CreatePostCommand } from './create-post.command.js';
@Injectable()
export class PostService {
commandBus: CommandBus;
constructor(commandBus: CommandBus) {
this.commandBus = commandBus;
}
async create(title: string) {
return this.commandBus.execute(
new CreatePostCommand(title),
);
}
}
Обработчик кладёт объект в массив и возвращает его вызывающему коду:
import { CommandHandler, ICommandHandler } from '@nestjs/cqrs';
import { CreatePostCommand } from './create-post.command.js';
@CommandHandler(CreatePostCommand)
export class CreatePostHandler
implements ICommandHandler<CreatePostCommand>
{
posts: { title: string }[] = [];
async execute(command: CreatePostCommand) {
const post = { title: command.title };
this.posts.push(post);
return post;
}
}
Контроллер принимает заголовок и отдаёт результат сервиса:
import { Body, Controller, Post } from '@nestjs/common';
import { PostService } from './post.service.js';
@Controller('posts')
export class PostController {
postService: PostService;
constructor(postService: PostService) {
this.postService = postService;
}
@Post()
create(@Body('title') title: string) {
return this.postService.create(title);
}
}
Подключите модуль команд
в корневом модуле. Опишите
CreateWorkerCommand,
отправляйте её из
WorkerService
через шину команд
и зарегистрируйте
CreateWorkerHandler,
который складывает работника
в массив в памяти.