深入淺析node中的Nest.js框架

2022-02-06 10:00:20
本篇文章帶大家認識一下中的Nest.js框架,聊聊為什麼選擇 Nest,建立和執行專案、不同方式接收請求的方法,希望對大家有所幫助!

最近在考慮和小夥伴做一個todolist平臺給自己用,很久之前學習過 express ,想著與時俱進一下,看看近期熱度較高的幾個框架是怎樣的。在幾個對比下選擇了 nest 在初步使用後記錄一下,方便日後查閱。

貼出中文檔案以便大家進一步學習 Nest

Nest.js框架簡介

  • Nest 是一個用於構建高效,可延伸的 伺服器端應用程式的框架。它使用漸進式 JavaScript,內建並完全支援 TypeScript(但仍然允許開發人員使用純 JavaScript 編寫程式碼)並結合了 OOP(物件導向程式設計),FP(函數語言程式設計)和 FRP(函數式響應程式設計)的元素。
  • Nest 框架底層 HTTP 平臺預設是基於 Express 實現的,所以無需擔心第三方庫的缺失。 Nest 旨在成為一個與平臺無關的框架。 通過平臺,可以建立可重用的邏輯部件,開發人員可以利用這些部件來跨越多種不同型別的應用程式。 nest 目前有兩個支援開箱即用的 HTTP 平臺:express 和 fastify 可以在專案中直接引入。

為什麼選擇 Nest

  • 目前市面上有很多 node 框架可供大家選擇。
  • Express.js 是 Node.JS 誕生之初,是一款基於Node.js以及Chrome V8引擎,快速、極簡的JS伺服器端開發框架。
  • Koa.js是一款微型Web框架,寫一個hello world很簡單,但web應用離不開session,檢視模板,路由,檔案上傳,紀錄檔管理。這些 Koa 都不提供,需要自行去官方的 Middleware 尋找。然而,100個人可能找出100種搭配。
  • Egg.js是基於Koa.js,解決了上述問題,將社群最佳實踐整合進了Koa.js,另取名叫Egg.js,並且將多程序啟動,開發時的熱更新等問題一併解決了。這對開發者很友好,開箱即用,開箱即是最(較)佳設定。Egg.js發展期間,ECMAScript又推出了 async await,相比yield的語法async寫起來更直。後面Koa.js也同步進行了跟進。
  • Midway 是阿里團隊,基於漸進式理念研發的 Node.js 框架,結合了 OOP和函數式兩種程式設計正規化。以 egg 是作為底層框架,加上了良好的TypeScript的定義支援等眾多新特性,推出了Midway,有興趣的小夥伴可以去官方檔案學習一下
  • Nest.js 基於Express.js的全功能框架 Nest.js,他是在Express.js上封裝的,充分利用了TypeScript的特性;Nest.js的優點是社群活躍,漲勢喜人,截止目前在 GitHub 擁有 43.7k Star 是近期比較熱門的企業級框架。
  • 基於支援底層支援ts與企業級和社群活躍度等綜合考慮,這裡我選擇用nest來進行學習。各位同學可以按需選擇。

建立專案

  • 確保電腦安裝了 Node.js (>= 10.13.0)

  • 這裡我使用的 node 版本為 v14.16.1 包用的是 yarn 管理的 版本為 1.22.17

建立專案

  • $  npm i -g @nestjs/cli
    $  nest new project-name
  • 建立好專案後看一下專案目錄,以下是核心檔案的簡單描述:

  • app.controller.ts帶有單個路由的基本控制器範例
    app.controller.spec.ts對於基本控制器的單元測試樣例
    app.module.ts應用程式的根模組。
    app.service.ts帶有單個方法的基本服務
    main.ts應用程式入口檔案。用來建立 Nest 應用範例。
    /* main.ts */
    import { NestFactory } from '@nestjs/core';
    import { AppModule } from './app.module';
    
    async function bootstrap() {
      const app = await NestFactory.create(AppModule); // 使用核心類 NestFactory 返回一個 介面物件
      await app.listen(3000);  // 這裡是預設設定的埠號
    }
    bootstrap();

執行專案

  • $ npm run start:watch // 啟動專案並監聽程式碼變動 這裡可以在package.json 中進行設定指令

1.png

  •   我們可以看到服務已經啟動,輸入本機地址並帶上埠號3000,傳送一次 get 請求 則會返回 `Hello World`。 
      
      這裡是因為在 app.controll.ts 檔案中 @Get()HTTP請求裝飾器告訴Nest為HTTP請求的特定端點建立處理程式。

路由

  • 在開始寫程式碼之前我們先簡單看一下nest中的基礎路由設定是怎樣的,就目前而言我的理解為nest的路由是由 全域性路由 路由字首(區域性路由) 方法裝飾器 組成路由對映提供給前端使用。

  •  /* main.ts */
     main檔案中我們可以在專案監聽前設定一個全域性的api字首
    async function bootstrap() {
    const app = await NestFactory.create(AppModule);
        //設定全域性字首
        app.setGlobalPrefix('api');
        await app.listen(3000);
      }
    /* app.controller.ts */
    @Controller('user') // 控制器設定路由字首 我理解為區域性路由
      export class AppController {
        constructor(private readonly appService: AppService) {}
        @Get('find') // 方法裝飾器設定路由路徑 這裡我理解為設定api子路由
        getHello(): string {
          return this.appService.getHello();
            }
        }
  • 以上方法在api中對映成完整的路由為GET api/user/find

  • 其中 @Get()HTTP請求裝飾器告訴Nest為HTTP請求的特定端點建立處理程式。

2.png

  • 可以看到上面的 get 接收請求及路由以可以使用,下面我們看一下 nest 中如何接收 post 等其他請求方式

不同方式接收請求

  • 這裡用到的 Nest 提供的請求裝飾器知識點Request 物件代表 HTTP 請求,並具有查詢字串,請求引數引數,HTTP 檔頭(HTTP header) 和 正文(HTTP body)的屬性(在這裡閱讀更多)。在多數情況下,不必手動獲取它們。 我們可以使用專用的裝飾器,比如開箱即用的 @Body()@Query() 。 下面是 Nest 提供的裝飾器及其代表的底層平臺特定物件的對照列表。

    3.png

  • 下面我們看一下 nest 中如何接收 get post put delete 發起的請求,用幾個可用的裝飾器來建立基本控制器。 該控制器暴露了幾個存取和操作內部資料的方法。

Get

  • 我們先建立一個 user 服務/控制器/moudle

    / * user.service.ts  */ 先建立一個 user service服務檔案
    import { Injectable } from '@nestjs/common';
       @Injectable() // 
       // 這裡
       export class UserService {
         findUser(sid: string): string {
           console.log(sid);
           if (sid === '123456') {
             return 'kid is here';
           }
           return 'No one here';
         }
      }
  • 該服務將負責資料儲存和檢索,其由 UserController 使用,我們用 @Injectable() 來裝飾這個類

    / * user.controller.ts  */ 建立一個 user 控制器檔案
    import { Controller, Get, Query } from '@nestjs/common';
    import { UserService } from './user.service';
    
    @Controller('user')
    export class UserController {
       constructor(private readonly userService: UserService) {}
       @Get('findOne') //這裡暴露出的路由為 user/find
       findUser(@Query() query: any) {
         return this.userService.findUser(query.sid);
       }
  • 控制器的目的是接收應用的特定請求。路由機制控制哪個控制器接收哪些請求。通常,每個控制器有多個路由,不同的路由可以執行不同的操作。

  • 為了建立一個基本的控制器,我們使用類和裝飾器。裝飾器將類與所需的後設資料相關聯,並使 Nest 能夠建立路由對映(將請求繫結到相應的控制器)。

    / * user.module.ts  */ 建立一個 user mod
     import { Module } from '@nestjs/common';
     import { UserController } from './user.controller';
     import { UserService } from './user.service';
     @Module({
         controllers: [UserController],
         providers: [UserService],
       })
       export class UserModule {}
    
    /*  app.module.ts  */ 最後在app.module中引入我們自己寫的module
    import { Module } from '@nestjs/common';
    import { AppController } from './app.controller';
    import { AppService } from './app.service';
    import { UserModule } from './user/user.module';
    
    @Module({
         imports: [UserModule],
         controllers: [AppController],
         providers: [AppService],
       })
       export class AppModule {}
  • 控制器已經準備就緒,可以使用,但是 Nest 依然不知道 UserController 是否存在,所以它不會建立這個類的一個範例。

  • 控制器總是屬於模組,這就是為什麼我們在 @Module() 裝飾器中包含 controllers 陣列的原因。 由於除了根模組 AppModule之外,我們還沒有定義其他模組,所以我們將使用它來介紹 UserController

    使用 postman 看下效果

    4.png

    • 可以看到傳送get請求 請求成攻。
    • 接下來我們依次使用 post put delete 傳送請求,看nest是如何接受並處理的

Post

  • user.service 檔案

    / * user.service.ts  */ 先建立一個 user service服務檔案
    import { Injectable } from '@nestjs/common';
       @Injectable() // 
       // 這裡
      setUser(sid: string, body: any): any {
           if (sid === '123456') {
             return {
               msg: '設定成功',
               body,
             };
         }
      }
  • user.controller 檔案

    / * user.controller.ts  */ 建立一個 user 控制器檔案
    import { Controller, Get, Query } from '@nestjs/common';
    import { UserService } from './user.service';
    
    @Controller('user')
    export class UserService {
        @Post('set')
        setUser(@Body() body: any, @Query() query: any) {
          return this.userService.setUser(query.sid, body);
        } 
    }

使用 postman 看下效果

5.png

  • 可以看到傳送 post 請求 請求成攻。

Put

  • user.service 檔案

    / * user.service.ts  */ 先建立一個 user service服務檔案
    import { Injectable } from '@nestjs/common';
       @Injectable() // 
       // 這裡
      updateUser(sid: string, body: any): any {
           if (sid === '123456') {
             return {
               msg: '設定成功',
               body,
             };
         }
      }
  • user.controller 檔案

  • 這裡用到了 Param 裝飾器 @Param() 用於修飾一個方法的引數(上面範例中的 params),並在該方法內將路由引數作為被修飾的方法引數的屬性。如上面的程式碼所示,我們可以通過參照 params.id來存取(路由路徑中的) id 引數。 您還可以將特定的引數標記傳遞給裝飾器,然後在方法主體中按引數名稱直接參照路由引數。

    / * user.controller.ts  */ 建立一個 user 控制器檔案
    import { Body, Controller, Get, Param, Post, Put, Query } from '@nestjs/common';
    import { UserService } from './user.service';
    
    @Controller('user')
    export class UserService {
       @Put(':sid')
       updateUser(@Param('sid') sid: string, @Body() body: any) {
         return this.userService.updateUser(sid, body);
       }
    }

使用 postman 看下效果

6.png

  • 可以看到傳送 put 請求 請求成攻。

Delete

  • user.service 檔案

    / * user.service.ts  */ 先建立一個 user service服務檔案
    import { Injectable } from '@nestjs/common';
       @Injectable() // 
       // 這裡
     deleteUser(sid: string): any {
           if (sid === '123456') {
             return {
               msg: '刪除成功',
             };
         }
      }
  • user.controller 檔案

    / * user.controller.ts  */ 建立一個 user 控制器檔案
    import { Body, Controller, Get, Param, Post, Put, Query } from '@nestjs/common';
    import { UserService } from './user.service';
    
    @Controller('user')
    export class UserService {
       @Delete(':sid')
       deleteUser(@Param('sid') sid: string) {
         return this.userService.deleteUser(sid);
       }
    }

使用 postman 看下效果

7.png

  • 可以看到傳送 delete 請求 請求成攻。

總結

  • 至此我們用 Nest 的裝飾器模擬了基礎的介面請求增刪改查,認識到 Nest 中的三種基本應用程式構建塊Module Controller Service
  • 服務和控制的劃分明確,帶來更好的程式碼體驗。TypeScrip 的個人使用還有待提高,以後還要繼續學習hhh

更多node相關知識,請存取:!

以上就是深入淺析node中的Nest.js框架的詳細內容,更多請關注TW511.COM其它相關文章!