介绍
Nest.js是一款构建高效可扩展的NodeJS的框架,同时支持javascript和typescript。底层默认使用Express框架,并在之上提供了一层抽象的封装,同时暴露Express的api。
安装
$ npm i -g @nestjs/cli
$ nest new project-name
...
$ npm run start
//第二步可能安装不成功:切换淘宝镜像源即可:npm config set registry https://registry.npm.taobao.org
//启动成功后,localhost:3000可看到'hello world'
Hello World项目解读
src
├── app.controller.spec.ts //?
├── app.controller.ts //带有单个路由的基本控制器示例
├── app.module.ts //应用程序的根模块
├── app.service.ts //?
└── main.ts //应用程序入口文件(使用 NestFactory 用来创建 Nest 应用实例)
//main.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
async function bootstrap() {
//create是核心类NestFactory的静态方法,用于创建应用实例;
//create()返回一个实现了INestApplication接口的对象,并提供了一组方法。
const app = await NestFactory.create(AppModule);
await app.listen(3000);
}
bootstrap(); //该异步函数负责引导我们的应用程序
内置平台(以Express为例)
引入@nestjs/platform-express
包即可直接使用,其暴露的api是NestExpressApplication
.
当你确实要访问Express底层API时,可将该平台类型传递给NestFactory.create()
,使用如下:
import { NestExpressApplication } from '@nestjs/platform-express'
...
const app = await NestFactory.create<NestExpressApplication>(AppModule);
控制器
//app.controller.ts
import { Controller, Get } from '@nestjs/common';
import { AppService } from './app.service';
@Controller()
export class AppController {
constructor(private readonly appService: AppService) {}
@Get()
getHello(): string {
return this.appService.getHello();
}
}
- 控制器负责处理传入的
请求
和向客户端返回响应
。 -
路由
机制决定哪个控制器接收哪些请求。通常每个控制器有多个路由,不同的路由可以执行不同的操作。 - 可以使用类和装饰器,创建一个基本的控制器。
- 装饰器将类与所需的元数据相关联,并使Nest能够创建路由映射(将请求绑定到相应的控制器)
1. 路由
// cats.controller.ts
import { Controller, Get } from '@nestjs/common';
@Controller('cats')
export class CatsController {
@Get()
findAll(): string {
return 'This action returns all cats';
}
}
- 装饰器中可设置前缀;使用路由前缀('cats')可将路由分组;
- Http请求方法装饰器(可携带路由信息)为下面的处理程序指定请求方法和路由。(GET /cats 或 GET /cats/profile等)
- 推荐的响应写法:请求处理程序只管返回数据,其余的交给Nest。当请求处理程序返回一个js对象/数组时,nest将自动序列化为json。当返回一个基本类型(string/number/boolean)时,只发送值,不序列化。
- 类库特有的响应写法:在函数签名通过 @Res() 注入类库特定的 响应对象(例如,Express),使用此函数,您具有使用该对象的响应处理函数。例如,使用 Express,您可以使用类似代码构建响应 response.status(200).send()。
- 响应的状态码默认情况下始终为 200,但使用 201 的 POST请求除外。可在处理程序级别添加 @HttpCode(...) 装饰器来轻松更改此行为 。
//使用CLI创建控制器,为项目增加对应路径下的控制器默认文件。
//项目根目录下,nest g controller xxx. (-g: generate的缩写)
$ nest g controller cats
//该命令还会自动将该控制器注册在app.module.ts中的module模块里面。
2. Request
当需求访问客户端的请求
细节。 可强制Nest
使用@Req()装饰器
将请求对象注入处理程序(不推荐)。
//cats.controller.ts
import { Controller, Get, Req } from '@nestjs/common'; //@Req是'请求对象注入装饰器'
import { Request } from 'express'; //开发依赖包中已安装了@types/express,因此此处可直接使用express,并从中导出Request作为类使用
@Controller('cats')
export class CatsController {
@Get()
findAll(@Req() req: Request): string {
console.log(req);
return 'This action returns all cats';
}
}
- 使用专用的装饰器,而非手动从
Request
对象中获取诸如:查询字符串,参数,http标头,正文。 - @Request()、@Response()、@Next()、@Session()、@Param(key?: string)、@Body(key?: string)、@Query(key?: string)、@Headers(name?: string)、@Ip()
3. 资源
即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';
}
}
端点装饰器还有:
- @Put()
- @Delete()
- @Patch()
- @Options()
- @Head()
- @All()
4. 路由通配符
路由支持模糊匹配,如
@Get('ab*cd')
findAll() {
return 'This route uses a wildcard';
}
5. 状态码
默认情况下,响应的状态码总是200,但 POST 请求是201。更改方式如下:
import { HttpCode } from '@nestjs/common';
@Post()
@HttpCode(204) //处理程序层添加该装饰器
create() {
return 'This action adds a new cat';
}
6. 响应头Headers
需要自定义响应头Headers,使用@Header或者类库特有的响应对象(略)
import { Header} from '@nestjs/common';
@Post()
@Header('Cache-Control', 'none')
create() {
return 'This action adds a new cat';
}
7. 重定向
将响应重定向到特定url。
@Get('docs')
@Redirect('https://docs.nestjs.com', 302)
getDocs(@Query('version') version) { //注意version的用法噶
if (version && version === '5') {
return { url: 'https://docs.nestjs.com/v5/' };
}
}
8. 路由参数
- 定义带参数的路由时,
@Get()
中可添加路由参数标记
。 - 将参数装饰器添加到函数签名中,就可以获取该路由参数。
import { Param} from '@nestjs/common';
@Get(':id')
findOne(@Param() params): string {
console.log(params.id);
return `This action returns a #${params.id} cat`;
}
//或
@Get(':id')
findOne(@Param('id') id): string {
console.log(params.id);
return `This action returns a #${id} cat`;
}
9. 子域路由
当传入请求的 HTTP 主机匹配某个特定值。
@Controller({ host: 'admin.example.com' })
export class AdminController {
@Get()
index(): string {
return 'Admin page';
}
}
//获取主机参数
@Controller({ host: ':account.example.com' })
export class AccountController {
@Get()
getInfo(@HostParam('account') account: string) {
return account;
}
10. Async/await ---???????????????
//cats.controller.ts
@Get()
async findAll(): Promise<any[]> {
return [];
}
Nest将自动订阅下面的源并获取最后发出的值(在流完成后):
@Get()
findAll(): Observable<any[]> {
return of([]);
}
10. 请求负载
即取出post()请求中的body。
- 假如使用Typescript,则需要确定
DTO模式
(数据传输对象
,它定义了如何通过网络发送数
据)。 - 建议使用简单的类而非接口来实现DTO。因为类是ES6的一部分,编译完后仍保留在源码中,在运行时仍可引用。
//create-cat.dto.ts
export class CreateCatDto {
readonly name: string;
readonly age: number;
readonly breed: string;
}
//cats.controller.ts
@Post()
async create(@Body() createCatDto: CreateCatDto) {
//如何使用????????
return 'This action adds a new cat';
}
- 从Post提交上来的body被命名为createCatDto,它是符合CreateCatDto类型的;
11. 完整示例
//cast.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`;
}
}
12. 类库的使用方法
- 谨慎使用类库
- 在可能的情况下,应始终首选 Nest 标准方法
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([]);
}
}
网友评论