(二) Controller

135 阅读3分钟

image.png

总体来说,Controller 就是一个处理客户端请求,并将相同性质的资源整合在一起的元件

image.png

image.png

import { Controller } from '@nestjs/common';

@Controller('todo')
export class TodoController {}

image.png

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 [];
  }
}

image.png

image.png

image.png

image.png

image.png

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 [];
  }
}

image.png

主體資料 (Body)

在传输资料时经常会使用到主体资料,比如说:POSTPUTPATCH等操作,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 的格式來設置驗證器,進而大幅降低維護成本。 既然是定義格式,那麼就有兩種選擇:

  1. TypeScript 的 interface
  2. 標準 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: ''
    };
  }
}

image.png

處理回應的方式

  1. 透過 return 資料的方式
  2. 非同步操作,這時候用 ES7 的 async/await 再好不過
  3. RxJS函式庫,Nest 會自動訂閱 / 取消訂閱對象,無須手動取消訂閱
  4. 使用底層框架的回應物件來處理回應,不透過 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 [];
  }
}

image.png