总体来说,Controller 就是一个处理客户端请求,并将相同性质的资源整合在一起的元件。
import { Controller } from '@nestjs/common';
@Controller('todo')
export class TodoController {}
Http Methods
可以透过添加装饰器在 class 的方法上,来指定不同 Http Method 所呼叫的方法,Nest 会根据 Controller 与指定的 Http Method 装饰器来建立路由表。以下方程式码为例,使用的为GET:
Nest 的 Http Method 装饰器名称即对应标准 Http Method,这里做了些归纳:
@Get:表示接收对应路由且为GET请求时触发。@Post:表示接收对应路由且为POST请求时触发。@Put:表示接收对应路由且为PUT请求时触发。@Patch:表示接收对应路由且为PATCH请求时触发。@Delete:表示接收对应路由且为DELETE请求时触发。@Options:表示接收对应路由且为OPTIONS请求时触发。@Head:表示接收对应路由且为HEAD请求时触发。@All:表示接收对应路由且为以上任何方式的请求时触发。
import { Controller, Get } from '@nestjs/common';
@Controller('todos')
export class TodoController {
@Get()
getAll() {
return [];
}
}
import { Controller, Get } from '@nestjs/common';
@Controller('todos')
export class TodoController {
@Get('exam*ples')
get() {
return [
{
id: 1,
title: 'Example 1',
description: ''
}
];
}
}
import { Controller, Get } from '@nestjs/common';
@Controller('todos')
export class TodoController {
@Get('exam*ples')
get() {
return [
{
id: 1,
title: 'Example 1',
description: ''
}
];
}
}
import { Controller, Get, Query } from '@nestjs/common';
@Controller('todos')
export class TodoController {
@Get()
getList(
@Query('limit') limit: number = 30,
@Query('skip') skip: number = 0
) {
const list = [
{
id: 1,
title: 'Title 1',
description: ''
},
{
id: 2,
title: 'Title 2',
description: ''
}
];
return list.slice(skip, limit);
}
}
import { Controller, Patch, HttpCode, HttpStatus } from '@nestjs/common';
@Controller('todos')
export class TodoController {
@Patch()
@HttpCode(HttpStatus.NO_CONTENT)
get() {
return [];
}
}
主體資料 (Body)
在传输资料时经常会使用到主体资料,比如说:POST、PUT、PATCH等操作,Nest 有提供 @Body 装饰器来取得主体资料
import { Body, Controller, Post } from '@nestjs/common';
@Controller('todos')
export class TodoController {
@Post()
create(
@Body('title') title: string,
@Body('description') description?: string
) {
const id = 1;
return { id, title, description };
}
}
使用 DTO
什麼是 DTO?它的全名是 資料傳輸物件 (Data Transfer Object) ,其用途廣泛,通常用於過濾、格式化資料,它只負責存放要傳遞的資訊,故 只有唯讀屬性,沒有任何方法。定義 DTO 之後,就不必一直翻文件查到底參數格式為何,可以很清楚了解傳入 / 傳出的參數內容,在 Nest 的世界裡,甚至可以基於 DTO 的格式來設置驗證器,進而大幅降低維護成本。 既然是定義格式,那麼就有兩種選擇:
- TypeScript 的
interface - 標準 JavaScript 支援的
class
基本上會建議大家採用 class 的形式來建立 DTO,原因是 interface 在編譯成 JavaScript 就會被刪除,而 class 會保留,這對部分功能是有影響的,所以 官方也推薦大家採用 class。
export class CreateTodoDto {
public readonly title: string;
public readonly description?: string;
}
import { Body, Controller, Post } from '@nestjs/common';
import { CreateTodoDto } from './dto/create-todo.dto';
@Controller('todos')
export class TodoController {
@Post()
create(@Body() dto: CreateTodoDto) {
const id = 1;
return { id, ...dto };
}
}
標頭 (Headers)
import { Controller, Get, Header } from '@nestjs/common';
@Controller('todos')
export class TodoController {
@Get()
@Header('X-Hao-headers', '1')
getAll() {
return {
id: 1,
title: 'Title 1',
description: ''
};
}
}
處理回應的方式
- 透過
return資料的方式 - 非同步操作,這時候用 ES7 的
async/await再好不過, - RxJS函式庫,Nest 會自動訂閱 / 取消訂閱對象,無須手動取消訂閱
- 使用底層框架的回應物件來處理回應,不透過
return的方式讓 Nest 處理,相當於每個方法都是void
import { Controller, Get } from '@nestjs/common';
@Controller('todos')
export class TodoController {
@Get()
getAll() {
return [];
}
}
import { Controller, Get } from '@nestjs/common';
@Controller('todos')
export class TodoController {
@Get()
async getAll() {
return new Promise((resolve, reject) => setTimeout(() => resolve([]), 1000));
}
}
import { Controller, Get, Res } from '@nestjs/common';
import { Response } from 'express';
@Controller('todos')
export class TodoController {
@Get()
getAll(@Res() res: Response) {
res.send([]);
}
}
import { Controller, Get } from '@nestjs/common';
import { of } from 'rxjs';
@Controller('todos')
export class TodoController {
@Get()
getAll() {
return of([]);
}
}
import { Controller, Get, Res } from '@nestjs/common';
import { Response } from 'express';
@Controller('todos')
export class TodoController {
@Get()
getAll(@Res({ passthrough: true }) res: Response) {
return [];
}
}