<!DOCTYPE html>
    <html lang="vi" xmlns="http://www.w3.org/1999/xhtml" prefix="og: http://ogp.me/ns#">
    <head>
<title>CQRS trong NestJS là gì?</title>
<meta name="description" content="CQRS trong NestJS là gì? - Savefile - Tin Tức - https&#x3A;&#x002F;&#x002F;www.nguoicodonvn2008.info&#x002F;vi&#x002F;news&#x002F;savefile&#x002F;kien-thuc-may-tinh&#x002F;cqrs-trong-nestjs-la-gi-6927.html">
<meta name="author" content=".: Nguoicodonvn2008.info - Cõi lòng người cô đơn :.">
<meta name="copyright" content=".: Nguoicodonvn2008.info - Cõi lòng người cô đơn :. [admin@nguoicodonvn2008.info]">
<meta name="robots" content="index, archive, follow, noodp">
<meta name="googlebot" content="index,archive,follow,noodp">
<meta name="msnbot" content="all,index,follow">
<meta name="generator" content="NukeViet v4.5">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta property="og:title" content="CQRS trong NestJS là gì?">
<meta property="og:type" content="website">
<meta property="og:description" content="Savefile - Tin Tức - https&#x3A;&#x002F;&#x002F;www.nguoicodonvn2008.info&#x002F;vi&#x002F;news&#x002F;savefile&#x002F;kien-thuc-may-tinh&#x002F;cqrs-trong-nestjs-la-gi-6927.html">
<meta property="og:site_name" content=".&#x3A; Nguoicodonvn2008.info - Cõi lòng người cô đơn &#x3A;.">
<meta property="og:url" content="https://www.nguoicodonvn2008.info/vi/news/savefile/kien-thuc-may-tinh/cqrs-trong-nestjs-la-gi-6927.html">
<link rel="shortcut icon" href="https://www.nguoicodonvn2008.info/favicon.ico">
<link rel="canonical" href="https://www.nguoicodonvn2008.info/vi/news/savefile/kien-thuc-may-tinh/cqrs-trong-nestjs-la-gi-6927.html">
<link rel="alternate" href="https://www.nguoicodonvn2008.info/vi/news/rss/" title="Tin Tức" type="application/rss+xml">
<link rel="alternate" href="https://www.nguoicodonvn2008.info/vi/news/rss/karaoke-dual/" title="Tin Tức - Karaoke Dual" type="application/rss+xml">
<link rel="alternate" href="https://www.nguoicodonvn2008.info/vi/news/rss/nhac-tre/" title="Tin Tức - Nhạc trẻ" type="application/rss+xml">
<link rel="alternate" href="https://www.nguoicodonvn2008.info/vi/news/rss/tru-tinh/" title="Tin Tức - Trữ tình" type="application/rss+xml">
<link rel="alternate" href="https://www.nguoicodonvn2008.info/vi/news/rss/nuoc-ngoai/" title="Tin Tức - Nước ngoài" type="application/rss+xml">
<link rel="alternate" href="https://www.nguoicodonvn2008.info/vi/news/rss/remix/" title="Tin Tức - Remix" type="application/rss+xml">
<link rel="alternate" href="https://www.nguoicodonvn2008.info/vi/news/rss/tam-su-tinh-yeu/" title="Tin Tức - Tâm sự tình yêu" type="application/rss+xml">
<link rel="alternate" href="https://www.nguoicodonvn2008.info/vi/news/rss/tho-suu-tam/" title="Tin Tức - Thơ sưu tầm" type="application/rss+xml">
<link rel="alternate" href="https://www.nguoicodonvn2008.info/vi/news/rss/cuoc-song/" title="Tin Tức - Cuộc sống" type="application/rss+xml">
<link rel="alternate" href="https://www.nguoicodonvn2008.info/vi/news/rss/phan-mem/" title="Tin Tức - Phần mềm" type="application/rss+xml">
<link rel="alternate" href="https://www.nguoicodonvn2008.info/vi/news/rss/kien-thuc-may-tinh/" title="Tin Tức - Kiến thức máy tính" type="application/rss+xml">
<link rel="alternate" href="https://www.nguoicodonvn2008.info/vi/news/rss/hoc-tap/" title="Tin Tức - Học tập" type="application/rss+xml">
<link rel="alternate" href="https://www.nguoicodonvn2008.info/vi/news/rss/tai-lieu/" title="Tin Tức - Tài liệu" type="application/rss+xml">
<link rel="alternate" href="https://www.nguoicodonvn2008.info/vi/news/rss/de-thi/" title="Tin Tức - Đề thi" type="application/rss+xml">
<link rel="preload" as="style" href="https://www.nguoicodonvn2008.info/assets/css/font-awesome.min.css" type="text/css">
<link rel="preload" as="style" href="https://www.nguoicodonvn2008.info/themes/default/css/bootstrap.non-responsive.css" type="text/css">
<link rel="preload" as="style" href="https://www.nguoicodonvn2008.info/themes/default/css/style.css" type="text/css">
<link rel="preload" as="style" href="https://www.nguoicodonvn2008.info/themes/default/css/style.non-responsive.css" type="text/css">
<link rel="preload" as="style" href="https://www.nguoicodonvn2008.info/themes/default/css/news.css" type="text/css">
<link rel="preload" as="style" href="https://www.nguoicodonvn2008.info/themes/default/css/custom.css" type="text/css">
<link rel="preload" as="script" href="https://www.nguoicodonvn2008.info/assets/js/jquery/jquery.min.js" type="text/javascript">
<link rel="preload" as="script" href="https://www.nguoicodonvn2008.info/assets/js/language/vi.js" type="text/javascript">
<link rel="preload" as="script" href="https://www.nguoicodonvn2008.info/assets/js/DOMPurify/purify3.js" type="text/javascript">
<link rel="preload" as="script" href="https://www.nguoicodonvn2008.info/assets/js/global.js" type="text/javascript">
<link rel="preload" as="script" href="https://www.nguoicodonvn2008.info/assets/js/site.js" type="text/javascript">
<link rel="preload" as="script" href="https://www.nguoicodonvn2008.info/themes/default/js/news.js" type="text/javascript">
<link rel="preload" as="script" href="https://www.nguoicodonvn2008.info/themes/default/js/main.js" type="text/javascript">
<link rel="preload" as="script" href="https://www.nguoicodonvn2008.info/themes/default/js/custom.js" type="text/javascript">
<link rel="preload" as="script" href="https://www.nguoicodonvn2008.info/themes/default/js/bootstrap.min.js" type="text/javascript">
<link rel="stylesheet" href="https://www.nguoicodonvn2008.info/assets/css/font-awesome.min.css">
<link rel="stylesheet" href="https://www.nguoicodonvn2008.info/themes/default/css/bootstrap.non-responsive.css">
<link rel="stylesheet" href="https://www.nguoicodonvn2008.info/themes/default/css/style.css">
<link rel="stylesheet" href="https://www.nguoicodonvn2008.info/themes/default/css/style.non-responsive.css">
<link rel="StyleSheet" href="https://www.nguoicodonvn2008.info/themes/default/css/news.css">
<link rel="stylesheet" href="https://www.nguoicodonvn2008.info/themes/default/css/custom.css">
<style type="text/css">
	body{background: #fff;}
</style>
    </head>
    <body>
<div id="print">
	<div id="hd_print">
		<h2 class="pull-left">.&#x3A; Nguoicodonvn2008.info - Cõi lòng người cô đơn &#x3A;.</h2>
		<p class="pull-right"><a title=".&#x3A; Nguoicodonvn2008.info - Cõi lòng người cô đơn &#x3A;." href="https://www.nguoicodonvn2008.info/">https://www.nguoicodonvn2008.info</a></p>
	</div>
	<div class="clear"></div>
	<hr />
	<div id="content">
		<h1>CQRS trong NestJS là gì?</h1>
		<ul class="list-inline">
			<li>Thứ bảy - 25/03/2023 00:24</li>
			<li class="hidden-print txtrequired"><em class="fa fa-print">&nbsp;</em><a title="In ra" href="javascript:;" onclick="window.print()">In ra</a></li>
			<li class="hidden-print txtrequired"><em class="fa fa-power-off">&nbsp;</em><a title="Đóng cửa sổ này" href="javascript:;" onclick="window.close()">Đóng cửa sổ này</a></li>
		</ul>
		<div class="clear"></div>
		<div id="hometext">
		</div>
				<div class="imghome">
			<img alt="CQRS trong NestJS là gì?" src="https://st.quantrimang.com/photos/image/2023/03/23/CQRS-NestJS-7.jpg" width="460" class="img-thumbnail" />
		</div>
		<div class="clear"></div>
		<div id="bodytext" class="clearfix">
			<p style="text-align: justify;">Dùng&nbsp;<strong>mẫu CQRS</strong>&nbsp;hợp lý, bạn có thể tạo ra những app NestJS sạch và dễ mở rộng hơn.</p>

<p style="text-align: justify;"><img alt="CQRS trong NestJS" data-i="0" data-src="https://st.quantrimang.com/photos/image/2023/03/23/CQRS-NestJS-7.jpg" data-was-processed="true" height="340" src="https://st.quantrimang.com/photos/image/2023/03/23/CQRS-NestJS-7.jpg" width="650" /></p>

<p style="text-align: justify;">Một phương pháp tiếp cận lập trình NestJS phổ biến là xây dựng các dịch vụ điều khiển giao tiếp để truy cập dữ liệu. Thế nhưng, hình thức này không phải là mẫu thiết kế hợp lệ duy nhất trong NestJS. Bạn còn có nhiều mẫu khác, trong đó bao gồm CQRS.</p>

<p style="text-align: justify;"><strong>CQRS&nbsp;</strong>là một mẫu thiết kế tách riêng các hoạt động đọc và viết của một ứng dụng. Sự phân tách này có thể giúp cải thiện khả năng mở rộng, hiệu suất và khả năng bảo trì.</p>

<p style="text-align: justify;">Dưới đây là<strong>&nbsp;mọi điều bạn cần biết về CQRS và cách áp dụng nó khi xây dựng một NestJS API</strong>.</p>

<h2 style="text-align: justify;">CQRS là gì?</h2>

<p style="text-align: justify;"><strong>CQRS</strong>&nbsp;là chữ viết tắt của<strong>&nbsp;command-query responsibility segregation</strong>. Nó dùng các lệnh để tạo, update, xóa dữ liệu và các truy vấn để tìm nạp dữ liệu. Điều này giúp loại bỏ nhu cầu triển khai các lệnh gọi cơ sở dữ liệu của ứng dụng vào dịch vụ.</p>

<p style="text-align: justify;">Nó cũng cho thấy sự phân biệt rõ ràng giữa logic truy vấn database cho dữ liệu và thực hiện các tác vụ khác trong ứng dụng.</p>

<p style="text-align: justify;">Phương pháp CQRS hữu ích trong thiết kế hướng tên miền. Điều này cho phép bạn tách riêng các hoạt động liên quan tới cơ sở hạ tầng và logic domain trong ứng dụng. Bạn cũng có thể dùng nó để triển khai logic nghiệp vụ phức tạp, nhưng không nên áp dụng cho những app đơn giản hơn.</p>

<h2 style="text-align: justify;">Dùng CQRS trong NestJS API</h2>

<p style="text-align: justify;">Bạn có thể dùng mẫu thiết kế CQRS trong một API đã dựng ở NestJS. Để tiếp tục, bạn cần cài Node.js trên máy tính và phiên bản NestJS mới nhất.</p>

<p style="text-align: justify;">Giờ làm theo những bước, bạn sẽ tạo được một app viết blog đơn giản bằng mẫu thiết kế CQRS.</p>

<h3 style="text-align: justify;">Tạo một dự án Nest</h3>

<p style="text-align: justify;">Tạp một dự án Nest mới cùng một nguồn&nbsp;<strong>post</strong>&nbsp;cho ứng dụng blog. Bạn có thể làm việc này bằng cách chạy lệnh sau trong terminal:</p>

<pre id="pre0">
<code>nest new nestjs-cqrs
nest g module posts
nest g controller posts
nest g service posts</code></pre>

<h3 style="text-align: justify;">Cài đặt các phần phụ thuộc</h3>

<p style="text-align: justify;">Sau khi đã hoàn thành các bước kể trên, chạy lệnh terminal này để cài gói NestJS CQRS:</p>

<pre id="pre1">
<code>npm install --save @nestjs/cqrs</code></pre>

<h3 style="text-align: justify;">Tạo một dịch vụ chuyển phát</h3>

<p style="text-align: justify;">Thêm code sau vào file&nbsp;<strong>posts.service.ts&nbsp;</strong>để xác định class&nbsp;<strong>PostService</strong>.</p>

<pre id="pre2">
<code>// posts.service.ts
import { Injectable } from &#039;@nestjs/common&#039;;

export interface Post {
    title: string;
    content: string;
}

@Injectable()
export class PostService {
  private readonly posts: Post&#91;&#93; = &#91;&#93;;

  create(post: Post): Post {
    this.posts.push(post);
    return post;
  }

  findById(id: number): Post {
    return this.posts.find(post =&gt; post.id === id);
  }
}</code></pre>

<p style="text-align: justify;"><strong>PostService</strong>&nbsp;định nghĩa phương thức&nbsp;<strong>create</strong>&nbsp;và&nbsp;<strong>findById</strong>&nbsp;để tạo một bài đăng mới, đồng thời lấy bài đăng hiện tại từ ID của nó.</p>

<h3 style="text-align: justify;">Định nghĩa các lệnh và truy vấn</h3>

<p style="text-align: justify;">Bước tiếp theo để định nghĩa truy vấn và lệnh là cốt lõi của mẫu thiết kế CQRS.</p>

<p style="text-align: justify;">Trong thư mục&nbsp;<strong>posts</strong>, tạo hai file mới:<strong>&nbsp;createPostCommand.command.ts&nbsp;</strong>&amp;&nbsp;<strong>getPostQuery.query.ts</strong>. File lệnh này trông sẽ như sau:</p>

<pre id="pre3">
<code>// createPostCommand.command.ts
export class CreatePostCommand {
  constructor(public readonly title: string, public readonly content: string) {}
}</code></pre>

<p style="text-align: justify;">Và file định nghĩ truy vấn trông sẽ như thế này:</p>

<pre id="pre4">
<code>// getPostQuery.query.ts
export class GetPostQuery {
  constructor(public readonly id: number) {}
}</code></pre>

<h2 style="text-align: justify;">Tạo lệnh và trình xử lý truy vấn</h2>

<p style="text-align: justify;">Sau khi thành công định nghĩa lệnh &amp; truy vấn, bạn cần tạo các trình xử lý cho chúng. Một trình xử lý là một hàm chạy lệnh hoặc truy vấn, rồi trả về kết quả.</p>

<p style="text-align: justify;">Tạo file&nbsp;<strong>handlers.ts&nbsp;</strong>trong thư mục post và dán code sau vào bên trong nó:</p>

<pre id="pre5">
<code>// handlers.ts
import { CommandHandler, ICommandHandler } from &#039;@nestjs/cqrs&#039;;
import { CreatePostCommand } from &#039;./createPostCommand.command.ts&#039;;
import { PostService } from &#039;./post.service&#039;;

@CommandHandler(CreatePostCommand)
export class CreatePostHandler implements ICommandHandler&lt;CreatePostCommand&gt; {
  constructor(private readonly postService: PostService) {}

  async execute(command: CreatePostCommand) {
    const { name, price } = command;
    const post = await this.postService.create(title, content);
    return post;
  }
}</code></pre>

<p style="text-align: justify;">Trong cùng file&nbsp;<strong>handlers.ts</strong>, bạn có thể chỉnh sửa các lệnh nhập để bao gồm code như bên dưới và cho phép làm việc với các truy vấn. Sau đó, bạn có thể chạy trình xử lý truy vấn như code bên dưới:</p>

<pre id="pre6">
<code>// handler.ts
import { QueryHandler, IQueryHandler } from &#039;@nestjs/cqrs&#039;;
import { GetPostQuery } from &#039;./getPostQuery.query&#039;;
import { PostService } from &#039;./post.service&#039;;

// query handler
@QueryHandler(GetProductQuery)
export class GetPostHandler implements IQueryHandler&lt;GetPostQuery&gt; {
  constructor(private readonly postService: PostService) {}

  async execute(query: GetPostQuery) {
    const { id } = query;
    const post = await this.postService.findOneById(id);
    return post;
  }
}</code></pre>

<h2 style="text-align: justify;">Trình xử lý Register</h2>

<p style="text-align: justify;">Bước cuối cùng là đăng ký lệnh và trình xử lý truy vấn bằng mô đun NestJS.</p>

<pre id="pre7">
<code>// post.module.ts
import { Module } from &#039;@nestjs/common&#039;;
import { CommandHandlers, QueryHandlers } from &#039;handlers.ts&#039;;
import { PostService } from &#039;./post.service&#039;;

@Module({
  providers: &#91;
    PostService,
    ...CommandHandlers,
    ...QueryHandlers,
  &#93;,
})
export class PostModule {}</code></pre>

<p style="text-align: justify;">Code này đăng ký&nbsp;<strong>PostService</strong>,&nbsp;<strong>CommandHandlers</strong>,&nbsp;<strong>QueryHandlers&nbsp;</strong>trong mảng<strong>&nbsp;providers</strong>. Dùng toán tử mở rộng (…) để hợp nhất các mảng của trình xử lý&nbsp;<strong>query</strong>&nbsp;và&nbsp;<strong>command&nbsp;</strong>vào mảng<strong>&nbsp;providers</strong>.</p>

<h3 style="text-align: justify;">Chạy lệnh và truy vấn</h3>

<p style="text-align: justify;">Các lệnh đã đăng ký cùng trình xử lý truy vấn có thể được dùng ở những controllers. Code sau triển khai một trình điều khiển&nbsp;<strong>post&nbsp;</strong>chấp nhận các truy vấn HTTP và trả về phản hồi cần thiết.</p>

<pre id="pre8">
<code>// posts.controller.ts
import { Body, Controller, Post } from &#039;@nestjs/common&#039;;
import { CommandBus } from &#039;@nestjs/cqrs&#039;;
import { CreatePostCommand } from &#039;./createPostCommand.command.ts&#039;;

// controller that implements command
@Controller(&#039;posts&#039;)
export class PostController {
  constructor(private readonly commandBus: CommandBus) {}

  @Post()
  async createPost(@Body() body: { title: string; content: string }) {
    const { title, content } = body;
    const command = new CreatePostCommand(title, content);
    const post = await this.commandBus.execute(command);
    return post;
  }
}</code></pre>

<p style="text-align: justify;">Ở code trên,&nbsp;<strong>CommandBus&nbsp;</strong>chạy&nbsp;<strong>CreatePostCommand</strong>&nbsp;và tạo một bài đăng mới. Code này hiện cách triển khai một controller dùng truy vấn:</p>

<pre id="pre9">
<code>// posts.controller.ts
import { Controller, Get, Param } from &#039;@nestjs/common&#039;;
import { QueryBus } from &#039;@nestjs/cqrs&#039;;
import { GetPostQuery } from &#039;./getPostQuery.query&#039;;

@Controller(&#039;posts&#039;)
export class PostController {
  constructor(private readonly queryBus: QueryBus) {}

  @Get(&#039;:id&#039;)
  async getPost(@Param(&#039;id&#039;) id: number) {
    const query = new GetPostQuery(id);
    const post = await this.queryBus.execute(query);
    return post;
  }
}</code></pre>

<p style="text-align: justify;"><strong>queryBus&nbsp;</strong>chạy<strong>&nbsp;GetPostQuery</strong>&nbsp;để nhận bài đăng chứa ID được cung cấp và trả về nó.</p>

<p style="text-align: justify;">Sau khi hoàn thành tất cả các bước trên, bạn sẽ có một ứng dụng hoạt động đơn giản trong việc tạo &amp; tìm nạp các bài viết trên blog.</p>

<p style="text-align: justify;">Trên đây là tất cả những điều bạn cần biết về mẫu thiết kế CQRS. Hi vọng bài viết hữu ích với các bạn.</p>
		</div>
				<div id="author">
						<p>
				<strong>Nguồn tin:</strong>
				Quantrimang.com
			</p>
		</div>
	</div>
	<div id="footer" class="clearfix">
		<div id="url">
			<strong>URL của bản tin này: </strong><a href="https://www.nguoicodonvn2008.info/vi/news/savefile/kien-thuc-may-tinh/cqrs-trong-nestjs-la-gi-6927.html" title="CQRS trong NestJS là gì?">https://www.nguoicodonvn2008.info/vi/news/savefile/kien-thuc-may-tinh/cqrs-trong-nestjs-la-gi-6927.html</a>

		</div>
		<div class="clear"></div>
		<div class="copyright">
			&copy; .&#x3A; Nguoicodonvn2008.info - Cõi lòng người cô đơn &#x3A;.
		</div>
		<div id="contact">
			<a href="mailto:admin@nguoicodonvn2008.info">admin@nguoicodonvn2008.info</a>
		</div>
	</div>
</div>
        <div id="timeoutsess" class="chromeframe">
            Bạn đã không sử dụng Site, <a onclick="timeoutsesscancel();" href="https://www.nguoicodonvn2008.info/#">Bấm vào đây để duy trì trạng thái đăng nhập</a>. Thời gian chờ: <span id="secField"> 60 </span> giây
        </div>
        <div id="openidResult" class="nv-alert" style="display:none"></div>
        <div id="openidBt" data-result="" data-redirect=""></div>
		</script>
		<div class="car-top">
  <span><img src="https://www.nguoicodonvn2008.info/themes/default/images/car.png" alt=""></span>
</div>
<script src="https://www.nguoicodonvn2008.info/assets/js/jquery/jquery.min.js"></script>
<script>var nv_base_siteurl="/",nv_lang_data="vi",nv_lang_interface="vi",nv_name_variable="nv",nv_fc_variable="op",nv_lang_variable="language",nv_module_name="news",nv_func_name="savefile",nv_is_user=0, nv_my_ofs=-4,nv_my_abbr="EDT",nv_cookie_prefix="nv4c_e856T",nv_check_pass_mstime=1738000,nv_area_admin=0,nv_safemode=0,theme_responsive=0,nv_recaptcha_ver=2,nv_recaptcha_sitekey="",nv_recaptcha_type="image",XSSsanitize=1;</script>
<script src="https://www.nguoicodonvn2008.info/assets/js/language/vi.js"></script>
<script src="https://www.nguoicodonvn2008.info/assets/js/DOMPurify/purify3.js"></script>
<script src="https://www.nguoicodonvn2008.info/assets/js/global.js"></script>
<script src="https://www.nguoicodonvn2008.info/assets/js/site.js"></script>
<script src="https://www.nguoicodonvn2008.info/themes/default/js/news.js"></script>
<script src="https://www.nguoicodonvn2008.info/themes/default/js/main.js"></script>
<script src="https://www.nguoicodonvn2008.info/themes/default/js/custom.js"></script>
<script type="application/ld+json">
        {
            "@context": "https://schema.org",
            "@type": "Organization",
            "url": "https://www.nguoicodonvn2008.info",
            "logo": "https://www.nguoicodonvn2008.info/uploads/angel.gif"
        }
        </script>
<script src="https://www.nguoicodonvn2008.info/themes/default/js/bootstrap.min.js"></script>
<script type="text/javascript">
var $scrolltop = $('.car-top');
$scrolltop.on('click', function () {
    $('html,body').animate({
        scrollTop: 0
    }, 800);
    $(this).addClass("car-run");
    setTimeout(function(){ $scrolltop.removeClass('car-run');}, 1000);
    return false;
});
$(window).on('scroll', function ()
{ 
    if($(window).scrollTop() >= 200)
    {
        $scrolltop.addClass("show");
        $scrolltop.addClass("car-down");
    }
    else
    {
       $scrolltop.removeClass("show");
       setTimeout(function(){ $scrolltop.removeClass('car-down');}, 300);
    }
});
</script>
</body>
</html>