欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Node.js控制器Controller使用教程

 更新時間:2023年04月14日 09:46:21   作者:zhouxiaoxiao2015  
這篇文章主要介紹了Node.js控制器Controller使用教程,一個控制器的目的是接收應(yīng)用程序的特定請求。路由機制控制哪個控制器接收哪些請求。通常,每個控制器有一個以上的路由,不同的路由可以執(zhí)行不同的動作

Controller 控制器

控制器負責(zé)處理傳入的請求并向客戶返回響應(yīng)。

一個控制器的目的是接收應(yīng)用程序的特定請求。路由機制控制哪個控制器接收哪些請求。通常,每個控制器有一個以上的路由,不同的路由可以執(zhí)行不同的動作。

為了創(chuàng)建一個基本的控制器,我們使用類和裝飾器。裝飾器將類與所需的元數(shù)據(jù)聯(lián)系起來,并使 Nest 能夠創(chuàng)建一個路由圖(將請求綁定到相應(yīng)的控制器)。

為了快速創(chuàng)建一個內(nèi)置驗證的 CRUD 控制器,你可以使用 CLI 的 CRUD 生成器:nest g resource [name]

路由

在下面的例子中,我們將使用@Controller()裝飾器,這是定義一個基本控制器所需要的。我們將指定一個可選的路由路徑前綴為cats。在@Controller()裝飾器中使用路徑前綴,可以讓我們輕松地將一組相關(guān)的路由分組,并盡量減少重復(fù)的代碼。例如,我們可以選擇將一組管理與客戶實體互動的路由歸入路由/customers。在這種情況下,我們可以在@Controller()裝飾器中指定路徑前綴customers,這樣我們就不必為文件中的每個路由重復(fù)這部分的路徑。

import { Controller, Get } from "@nestjs/common";
@Controller("cats")
export class CatsController {
  @Get()
  findAll(): string {
    return "This action returns all cats";
  }
}

要使用 CLI 創(chuàng)建一個控制器,只需執(zhí)行$ nest g controller cats命令。

findAll()方法之前的@Get() HTTP 請求方法裝飾器,告訴 Nest 為 HTTP 請求的特定端點創(chuàng)建一個處理程序。端點與 HTTP 請求方法(本例中為 GET)和路由路徑相對應(yīng)。

什么是路由路徑?處理程序的路徑是通過連接控制器聲明@Controller('cats')中的cats,以及方法裝飾器@Get()中指定的任何路徑來確定的。由于我們已經(jīng)為每個路由(cats)聲明了一個前綴,并且沒有在裝飾器@Get()中添加任何路徑信息,Nest 就會將GET /cats請求映射到findAll()的Get方法上來。

如前所述,路徑包括@Controller()路徑前綴和請求方法findAll()裝飾器@Get()中配置的路徑。例如,@Controller('customers')的路徑前綴與裝飾器@Get('profile')相結(jié)合,將產(chǎn)生一個GET /customers/profile這樣的路由映射請求。

在我們上面的例子中,當向該端點發(fā)出 GET 請求時,Nest 將該請求路由到我們用戶定義的 findAll()方法。注意,我們在這里選擇的方法名稱是完全任意的。顯然,我們必須聲明一個方法來綁定路由,但 Nest 并不重視所選擇的方法名稱的任何意義。

這個方法將返回一個 200 狀態(tài)代碼和相關(guān)的響應(yīng),在這種情況下,它只是一個字符串。為什么會發(fā)生這種情況?為了解釋,我們首先要介紹一個概念,即 Nest 采用了兩種不同的選項來操作響應(yīng)。

選項描述
Standard (recommended)使用這種內(nèi)置方法,當請求處理程序返回一個 JavaScript 對象或數(shù)組時,它將自動被序列化為 JSON。然而,當它返回一個 JavaScript 原始類型(例如,字符串、數(shù)字、布爾值)時,Nest 將只發(fā)送值,而不嘗試對其進行序列化。這使得響應(yīng)處理變得簡單:只需返回值,Nest 就會處理其余的事情。此外,響應(yīng)的狀態(tài)代碼默認總是 200,除了使用 201 的 POST 請求。我們可以通過在處理程序級別添加@HttpCode(…)裝飾器來輕松改變這一行為(見狀態(tài)代碼)。
Library-specific我們可以使用庫特定的(例如 Express)響應(yīng)對象,它可以使用方法處理簽名中的@Res()裝飾器注入(例如 findAll(@Res() response))。通過這種方法,你有能力使用該對象所暴露的本地響應(yīng)處理方法。例如,在 Express 中,你可以使用 response.status(200).send()這樣的代碼來構(gòu)造響應(yīng)。

警告:

NEST 會檢測處理程序是否使用@Res()或@Next(),表明你選擇了庫的特定選項。如果同時使用這兩種方法,標準方法將自動禁用于該單一路由,并不再按預(yù)期工作。要同時使用這兩種方法(例如,通過注入響應(yīng)對象只設(shè)置 cookie/頭文件,但仍將其余部分留給框架),你必須在@Res({ passthrough: true })裝飾器中將 passthrough 選項設(shè)置為 true。

請求對象

處理程序經(jīng)常需要訪問客戶端的請求細節(jié)。Nest 提供了對底層平臺(默認為 Express)的請求對象的訪問。我們可以通過在處理程序的簽名中添加@Req()裝飾器來指示 Nest 注入請求對象來訪問它。

import { Controller, Get, Req } from "@nestjs/common";
import { Request } from "express";
@Controller("cats")
export class CatsController {
  @Get()
  findAll(@Req() request: Request): string {
    return "This action returns all cats";
  }
}

為了利用表達式類型的優(yōu)勢(如上面的 request: Request 參數(shù)的例子),請安裝@types/express 包。

請求對象代表了 HTTP 請求,并有請求查詢字符串、參數(shù)、HTTP 頭和正文的屬性(在此閱讀更多內(nèi)容)。在大多數(shù)情況下,沒有必要手動抓取這些屬性。我們可以使用專門的裝飾器來代替,比如@Body()@Query(),這些裝飾器開箱即用。下面是一個所提供的裝飾器的列表,以及它們所代表的普通平臺特定對象。

裝飾器特定對象
@Request(), @Req()req
@Response(), @Res()*res
@Next()next
@Session()req.session
@Param(key?: string)req.params / req.params[key]
@Body(key?: string)req.body / req.body[key]
@Query(key?: string)req.query / req.query[key]
@Headers(name?: string)req.headers / req.headers[name]
@Ip()req.ip
@HostParam()req.hosts

為了與跨底層 HTTP 平臺(例如ExpressFastify)的類型兼容,Nest 提供了@Res()@Response()裝飾器。@Res()@Response() 的簡單別名。兩者都直接暴露了底層的本地平臺響應(yīng)對象接口。當使用它們時,你也應(yīng)該導(dǎo)入底層庫的類型(例如,@types/express)以充分利用。請注意,當你在方法處理程序中注入@Res()@Response()時,你將 Nest 放入該處理程序的庫特定模式中,并且你將負責(zé)管理響應(yīng)。當這樣做時,你必須通過調(diào)用響應(yīng)對象(如 res.json(...)res.send(...))來發(fā)出某種響應(yīng),否則 HTTP 服務(wù)器會掛起。

如何定義自己的裝飾器,請學(xué)習(xí)這個章節(jié)

資源

早些時候,我們定義了一個方法來獲取cats的資源(GET 路由)。我們通常也想提供一個創(chuàng)建新記錄的方法。為此,讓我們創(chuàng)建一個 POST 方法。

import { Controller, Get, Post } from "@nestjs/common";
@Controller("cats")
export class CatsController {
  @Post()
  create(): string {
    return "This action adds a new cat";
  }
  @Get()
  findAll(): string {
    return "This action returns all cats";
  }
}

就是這么簡單。Nest 為所有的標準 HTTP 方法提供裝飾器。 @Get(), @Post(), @Put(), @Delete(), @Patch(), @Options(), 和 @Head()。此外,@All()定義了一個可以處理所有這些方法的端點。

路由通配符

基于路由的模式也被支持。例如,*被用作通配符,將匹配任何字符的組合。

@Get('ab*cd')
findAll() {
  return 'This route uses a wildcard';
}

ab*cd 路由路徑將匹配 abcd、ab_cd、abecd,等等。字符"?“、”+“、”*“和”()"可以在路徑中使用,它們是對應(yīng)于正則表達式的子集。連字符(-)和點(.)可以通過基于字符串的路徑進行字面解釋。

狀態(tài)代碼

如前所述,響應(yīng)狀態(tài)代碼默認總是 200,除了 POST 請求是 201。我們可以通過在處理程序級別添加@HttpCode(...)裝飾器來輕松改變這一行為。

@Post()
@HttpCode(204)
create() {
  return 'This action adds a new cat';
}

@nestjs/common包導(dǎo)入HttpCode

通常,你的狀態(tài)代碼不是靜態(tài)的,而是取決于各種因素。在這種情況下,你可以使用一個庫特定的響應(yīng)(使用@Res()注入)對象(或者,在出現(xiàn)錯誤時,拋出一個異常)。

頭信息

要指定一個自定義的響應(yīng)頭,你可以使用@Header()裝飾器或一個庫特定的響應(yīng)對象(并直接調(diào)用res.header())。

@Post()
@Header('Cache-Control', 'none')
create() {
  return 'This action adds a new cat';
}

@nestjs/common包導(dǎo)入Header

重定向

要將一個響應(yīng)重定向到一個特定的 URL,你可以使用@Redirect()裝飾器或一個庫特定的響應(yīng)對象(并直接調(diào)用res.redirect())。

@Redirect()需要兩個參數(shù),urlstatusCode,都是可選的。如果省略的話,statusCode的默認值是302。

@Get()
@Redirect('https://nestjs.com', 301)

有時你可能想動態(tài)地確定 HTTP 狀態(tài)代碼或重定向 URL。通過從路由處理方法中返回一個對象來做到這一點,類似如下。

{
  "url": string,
  "statusCode": number
}

返回的值將覆蓋傳遞給@Redirect()裝飾器的任何參數(shù)。比如說。

@Get('docs')
@Redirect('https://docs.nestjs.com', 302)
getDocs(@Query('version') version) {
  if (version && version === '5') {
    return { url: 'https://docs.nestjs.com/v5/' };
  }
}

路由參數(shù)

當你需要接受動態(tài)數(shù)據(jù)作為請求的一部分時,帶有靜態(tài)路徑的路由將無法工作(例如,GET /cats/1 以獲得 id 為 1 的貓)。為了定義帶參數(shù)的路由,我們可以在路由的路徑中添加路由參數(shù)令牌,以捕獲請求 URL 中該位置的動態(tài)值。下面@Get()裝飾器例子中的路由參數(shù)令牌展示了這種用法。以這種方式聲明的路由參數(shù)可以使用@Param()裝飾器進行訪問,它應(yīng)該被添加到方法簽名中。

@Get(':id')
findOne(@Param() params): string {
  console.log(params.id);
  return `This action returns a #${params.id} cat`;
}

@Param()被用來裝飾一個方法參數(shù)(上面例子中的params),并使路由參數(shù)作為該方法主體中被裝飾的方法參數(shù)的屬性可用。正如上面的代碼所見,我們可以通過引用params.id來訪問id參數(shù)。你也可以向裝飾器傳遞一個特定的參數(shù)標記,然后在方法主體中直接引用路由參數(shù)的名稱。

@nestjs/common包導(dǎo)入Param

@Get(':id')
findOne(@Param('id') id: string): string {
  return `This action returns a #${id} cat`;
}

子域路由

@Controller裝飾器可以接受一個host選項,要求傳入的請求的 HTTP 主機與某些特定的值相匹配。

@Controller({ host: "admin.example.com" })
export class AdminController {
  @Get()
  index(): string {
    return "Admin page";
  }
}

由于 Fastify 缺乏對嵌套路由器的支持,當使用子域路由時,應(yīng)該使用(默認)Express 適配器來代替

與路由路徑類似,hosts選項可以使用令牌來捕獲主機名稱中該位置的動態(tài)值。下面@Controller()裝飾器例子中的主機參數(shù)令牌展示了這種用法。以這種方式聲明的主機參數(shù)可以使用@HostParam()裝飾器進行訪問,它應(yīng)該被添加到方法簽名中。

@Controller({ host: ":account.example.com" })
export class AccountController {
  @Get()
  getInfo(@HostParam("account") account: string) {
    return account;
  }
}

范疇

對于來自不同編程語言背景的人來說,要知道在 Nest 中,幾乎所有的東西都是在傳入的請求中共享的,這可能是意想不到的。我們有一個到數(shù)據(jù)庫的連接池,有全局狀態(tài)的單體服務(wù),等等。請記住,Node.js 并不遵循請求/響應(yīng)的多線程無狀態(tài)模型,其中每個請求都由一個單獨的線程來處理。因此,使用單體實例對我們的應(yīng)用程序是完全安全的。

但是,在極端情況下,基于請求的控制器生存周祁可能是所需的行為(However, there are edge-cases when request-based lifetime of the controller may be the desired behavior),例如 GraphQL 應(yīng)用程序中的每個請求緩存,請求跟蹤或多租戶。在這里了解如何控制作用域。

異步性

我們熱愛現(xiàn)代 JavaScript,我們知道數(shù)據(jù)提取大多是異步的。這就是為什么 Nest 支持并能很好地使用異步函數(shù)。

學(xué)習(xí)async / await請點擊這里

每個異步函數(shù)都必須返回一個 Promise。這意味著你可以返回一個延遲值,Nest 將能夠自己解決。讓我們來看看這個例子。

@Get()
async findAll(): Promise<any[]> {
  return [];
}

上述代碼是完全有效的。此外,Nest 路由處理程序通過能夠返回 RxJS 可觀察流而變得更加強大。Nest 將自動訂閱下面的源并獲取最后一個發(fā)出的值(一旦流完成)–( Nest will automatically subscribe to the source underneath and take the last emitted value (once the stream is completed))

@Get()
findAll(): Observable<any[]> {
  return of([]);
}

上述兩種方法都有效,你可以使用任何符合你要求的方法。

請求的有效載荷

我們之前的 POST 路由處理器的例子沒有接受任何客戶端參數(shù)。讓我們通過在這里添加@Body()裝飾器來解決這個問題。

但首先(如果你使用 TypeScript),我們需要確定 DTO(數(shù)據(jù)傳輸對象)模式。DTO 是一個定義了數(shù)據(jù)如何在網(wǎng)絡(luò)上發(fā)送的對象。我們可以通過使用 TypeScript 接口,或通過簡單的類來確定 DTO 模式。有趣的是,我們在這里推薦使用類。為什么呢?類是 JavaScript ES6 標準的一部分,因此它們在編譯后的 JavaScript 中被保留為真實的實體。另一方面,由于 TypeScript 接口在轉(zhuǎn)譯過程中被移除,Nest 不能在運行時引用它們。這一點很重要,因為像管道這樣的功能在運行時可以訪問變量的元類型,從而實現(xiàn)更多的可能性。

我們來創(chuàng)建CreateCatDto類。

export class CreateCatDto {
  name: string;
  age: number;
  breed: string;
}

它只有三個基本屬性。此后我們可以在CatsController中使用新創(chuàng)建的DTO。

我們的 Validation Pipe 可以過濾掉那些不應(yīng)該被方法處理程序接收的屬性。在這種情況下,我們可以將可接受的屬性列入白名單,任何不包括在白名單中的屬性都會自動從結(jié)果對象中剝離。在CreateCatDto的例子中,我們的白名單是名稱、年齡和品種屬性。在這里了解更多。

處理錯誤

這里有一個關(guān)于處理錯誤的單獨章節(jié)(即,與異常一起工作)。

完整例子

下面是一個例子,利用幾個可用的裝飾器來創(chuàng)建一個基本的控制器。這個控制器暴露了一些方法來訪問和操作內(nèi)部數(shù)據(jù)。

import {
  Controller,
  Get,
  Query,
  Post,
  Body,
  Put,
  Param,
  Delete,
} from "@nestjs/common";
import { CreateCatDto, UpdateCatDto, ListAllEntities } from "./dto";
@Controller("cats")
export class CatsController {
  @Post()
  create(@Body() createCatDto: CreateCatDto) {
    return "This action adds a new cat";
  }
  @Get()
  findAll(@Query() query: ListAllEntities) {
    return `This action returns all cats (limit: ${query.limit} items)`;
  }
  @Get(":id")
  findOne(@Param("id") id: string) {
    return `This action returns a #${id} cat`;
  }
  @Put(":id")
  update(@Param("id") id: string, @Body() updateCatDto: UpdateCatDto) {
    return `This action updates a #${id} cat`;
  }
  @Delete(":id")
  remove(@Param("id") id: string) {
    return `This action removes a #${id} cat`;
  }
}

Nest CLI 提供了一個自動生成器(示意圖),自動生成所有的模板代碼,以幫助我們避免做這些事情,并使開發(fā)人員的體驗更加簡單。在這里閱讀更多關(guān)于這個功能的信息。

開始運行

隨著上述控制器的完全定義,Nest 仍然不知道CatsController的存在,因此不會創(chuàng)建這個類的實例。

控制器總是屬于一個模塊,這就是為什么我們在@Module()裝飾器中包含控制器數(shù)組。由于我們還沒有定義任何其他模塊,除了根AppModule,我們將用它來介紹CatsController。

import { Module } from "@nestjs/common";
import { CatsController } from "./cats/cats.controller";
@Module({
  controllers: [CatsController],
})
export class AppModule {}

我們使用@Module()裝飾器將元數(shù)據(jù)附加到模塊類,Nest 現(xiàn)在可以很容易地反映出哪些控制器必須被安裝。

庫的特定方法

到目前為止,我們已經(jīng)討論了操作響應(yīng)的 Nest 標準方式。操作響應(yīng)的第二種方式是使用庫特定的響應(yīng)對象。為了注入一個特定的響應(yīng)對象,我們需要使用 @Res() 裝飾器。為了顯示差異,讓我們把CatsController重寫成以下內(nèi)容。

import { Controller, Get, Post, Res, HttpStatus } from "@nestjs/common";
import { Response } from "express";
@Controller("cats")
export class CatsController {
  @Post()
  create(@Res() res: Response) {
    res.status(HttpStatus.CREATED).send();
  }
  @Get()
  findAll(@Res() res: Response) {
    res.status(HttpStatus.OK).json([]);
  }
}

雖然這種方法是可行的,而且事實上通過提供對響應(yīng)對象的完全控制,在某些方面確實有更大的靈活性(頭文件的操作、庫的特定功能等等),但是應(yīng)該謹慎使用。一般來說,這種方法不那么明確,而且確實有一些缺點。主要的缺點是,你的代碼變得依賴于平臺(因為底層庫在響應(yīng)對象上可能有不同的 API),而且更難測試(你必須模擬響應(yīng)對象,等等)。

另外,在上面的例子中,你失去了與依賴 Nest 標準響應(yīng)處理的 Nest 功能的兼容性,如攔截器和@HttpCode() / @Header() 裝飾器。為了解決這個問題,你可以將 passthrough 選項設(shè)置為 true,如下所示。

@Get()
findAll(@Res({ passthrough: true }) res: Response) {
  res.status(HttpStatus.OK);
  return [];
}

現(xiàn)在,你可以與本地響應(yīng)對象進行交互(例如,根據(jù)某些條件設(shè)置 cookies 或頭信息),但把其余的事情留給框架。

到此這篇關(guān)于Node.js控制器Controller使用教程的文章就介紹到這了,更多相關(guān)Node.js Controller內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論