nest.js

简介

安装

可以使用 Nest CLI 创建项目,也可以克隆一个项目(两者的结果是一样的)。

使用 Nest CLI 构建项目

$ npm i -g @nestjs/cli
$ nest new project-name

其他安装方式

使用 Git 安装基于 TypeScript 的项目

$ git clone https://github.com/nestjs/typescript-starter.git project
$ cd project
$ npm install
$ npm run start

要安装基于 JavaScript 的项目,执行上面的命令时使用 javascript-starter.git

还可以通过 npmyarn安装核心和支撑文件,这种情况下,你将自己创建项目样板文件。

$ npm i --save @nestjs/core @nestjs/common rxjs reflect-metadata

概述

第一步

新建

$ npm i -g @nestjs/cli
$ nest new project-name

src/目录几个核心文件。

  • app.controller.spec.ts
  • app.controller.ts
  • app.module.ts
  • app.service.ts
  • main.ts
app.controller.ts 具有单一路由的基本控制器。
app.controller.spec.ts 单元测试控制器。
app.module.ts 应用程序的根模块。
app.service.ts 具有单一方法的基本服务。
main.ts 应用程序的入口文件,它使用核心NestFactory类创建Nest应用程序的实例。
import {
    NestFactory } from '@nestjs/core';
import {
    AppModule } from './app.module';

async function bootstrap() {
   
  const app = await NestFactory.create(AppModule);
  await app.listen(3000);
}
bootstrap();

默认情况下,发生任何错误,应用程序将以错误码1退出。如果想让它抛出一个错误,禁用abortOnError选项,如NestFactory.create( AppModule, {abortOnError: false} )

平台

两种平台开箱即用expressfastify

platform-express Express一个著名的极简web框架。默认使用@nestjs/platform-express
platform-fastify Fastify一个高性能和低开销的框架,高度关注提供最大的效率和速度。

无论哪个平台,都公开自己的接口。分别被视为NestExpressApplicationNestFastifyApplication

将一个类型传递给NestFactory.create(),应用程序对象将有该平台的方法。除非要访问平台API,否则不用指定类型。

const app = await NestFactory.create<NestExpressApplication>(AppModule);

控制器

控制器处理传入请求并向客户端返回响应。

创建有内置验证的CRUD控制器

$ nest g resource [name]

路由

@Controller()装饰器是定义控制器所必需的。在@Controller()装饰器中指定路径前缀cats可对一组相关路由分组。

//cats.controller.ts
import {
    Controller, Get } from '@nestjs/common';

@Controller('cats')
export class CatsController {
   
  @Get()
  findAll(): string {
   
    return 'This action returns all cats';
  }
}

使用CLI创建控制器

$ nest g controller cats

@Get()装饰器,装饰请求处理方法。

该方法返回200状态码和响应, 介绍两种不同响应:

Standard (recommended)标准(推荐) 使用这个内置方法,请求返回对象或数组时,自动序列化为JSON。返回基本类型(如,字符串,数字,布尔值)时只发送值不尝试序列化它。响应状态码默认是200,除了使用201POST请求。添加@HttpCode(…)装饰器,可以改变状态码。
Library-specific
特定库
使用特定库(如Express)的响应对象,它可以使用@Res()装饰器注入(如,findAll(@Res() response))。使用类似response.status(200).send()的响应。

Nest检测使用@Res()@Next()。同时使用两种方法,则标准方法将对这条路由自动禁用,不再像预期那样工作。要同时使用两种方法(如,通过注入响应对象只设置cookies/headers,其余工作留给框架),必须在@Res({ passthrough: true })装饰器中将passthrough 设置为true

请求对象

Nest提供了对底层平台(默认为Express)请求对象的访问。添加@Req()装饰器注入请求对象,从而访问请求对象。

//cats.controller.ts
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';
  }
}

安装@types/express便于类型提示。

请求对象有查询字符串、参数、HTTP头和主体等属性。使用专用的装饰器,如@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

注入@Res()@Response()时,Nest变成Library-specific模式,您将负责管理响应。必须调用响应对象(如res.json(…)res.send(…))发出相应类型的响应,否则HTTP服务器将挂起。

资源

创建POST处理程序:

//cats.controller.ts
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等。字符?, +, *()可以在路由路径中使用,它们对应正则表达式的子集。

状态码

响应状态码默认是200, POST请求除外,它是201。在处理程序级别添加@HttpCode(…)装饰器可改变状态码

import HttpCode from '@nestjs/common'

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

状态码不是静态的,而取决于各种因素。在这种情况下,您可以使用library-specific的响应对象(@Res()注入),或在发生错误时抛出异常。

自定义响应头,使用@Header()装饰器或特定库(library-specific)的响应对象(调用res.header())。

import Header from '@nestjs/common'

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

重定向

将响应重定向到特定URL,使用@Redirect()装饰器或特定库(library-specific)的响应对象(调用res.redirect())。

@Redirect()有两个参数,urlstatusCode,都是可选的。如果省略,statusCode的默认值是302

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

动态确定HTTP状态码或重定向URL。通过路由控制方法返回特定对象实现:

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

@Redirect()装饰器参数被返回值覆盖。例如:

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

路由参数

路由参数使用@Param()装饰器访问。

import Param from '@nestjs/common'

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

参数传递给@Param()装饰器,通过名称使用参数。

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

子域路由

@Controller装饰器传入含host属性对象,请求需匹配特定值。

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

Fastify缺乏对嵌套路由器的支持,使用子域路由时,应使用(默认)Express适配器。

host选项可以使用标记捕获主机名中该位置的动态值。使用@HostParam()装饰器访问主机参数。

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

作用域

几乎所有内容共享。数据库连接池,全局状态单例服务等。Node.js不遵循请求/响应多线程无状态模型,每个请求由单独线程处理。

某些情况下,控制器基于请求的生命周期是所需的行为,如GraphQL应用程序中请求缓存、请求跟踪或多租户。

异步性

async返回Promise

//cats.controller.ts

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

Nest路由处理程序甚至更强大,它能够返回RxJS可观察流(observable streams)。Nest自动订阅底层的源并接受最后发出的值(一旦流完成)。

//cats.controller.ts

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

请求有效载荷

添加@Body()装饰器。

使用TypeScript,需要确定DTO(数据传输对象)。

//create-cat.dto.ts

export class CreateCatDto {
   
  name: string;
  age: number;
  breed: string;
}
//cats.controller.ts

@Post()
async create(@Body() createCatDto: CreateCatDto) {
   
  return 'This action adds a new cat';
}

ValidationPipe可以过滤掉不该被接收的属性。将可接受的属性列入白名单,没有在白名单中的属性将从结果对象中删除。在CreateCatDto示例中,白名单是名称、年龄和品种属性。

完整的资源示例

//cats.controller.ts

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操作响应的标准方式。操作响应的第二种方式是使用特定库(library-specific)的响应对象。注入特定的响应对象,使用@Res()装饰器。

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

对响应对象完全控制(头操作、特定库的特性等)。缺点,代码依赖指定库(响应对象api不同),难测试(模拟响应对象等)。

失去与Nest特性(依赖于Nest标准响应)的兼容性,如Interceptors(拦截器)和@HttpCode() / @Header()装饰器。解决这个问题,设置passthroughtrue

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

现在根据条件设置cookiesheaders,其余工作留给框架。

提供者

提供者是基本概念。许多基本类被视为提供者——服务(services)、存储库(repositories)、工厂(factories)、助手(helpers)等。提供者主要思想是作为依赖注入; 意味着对象之间可以创建各种关系,“连接”对象实例可以委托给运行系统。

构建的CatsController。控制器处理HTTP请求,复杂的任务委派给提供者。提供者是声明为提供者的普通类。

服务

//cats.service.ts

import {
    Injectable } from '@nestjs/common';
import {
    Cat } from './interfaces/cat.interface';

@Injectable()
export class CatsService {
   
  private readonly cats: Cat[] = [];

  create(cat: Cat) {
   
    this.cats.push(cat);
  }

  findAll(): Cat[] {
   
    return this.cats;
  }
}

@Injectable()装饰器附加了元数据(metadata),声明CatsService是个由Nest IoC容器管理的类。

//interfaces/cat.interface.ts

export interface Cat {
   
  name: string;
  age: number;
  breed: string;
}
//cats.controller.ts

import {
    Controller, Get, Post, Body } from '@nestjs/common';
import {
    CreateCatDto } from './dto/create-cat.dto';
import {
    CatsService } from './cats.service';
import {
    Cat } from './interfaces/cat.interface';

@Controller('cats')
export class CatsController {
   
  constructor(private catsService: CatsService) {
   }

  @Post()
  async create(

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值