nestjs快速上手指南

Nestjs是一个基于Nodejs的服务器框架,吸收和借鉴了前端框架Angular的风格,完全支持TypeScript语言,因此,对于熟悉Angular以及TypeScript的用户来说,是服务器端编程的不二选择。在底层,Nestjs支持流行的Express(默认)框架,但也可以选择Fastify框架进行开发。


nestjs快速上手指南


1.Nestjs安装与快速启动


1.1 nestjs安装


Nestjs项目可以通过命令行,git或者手动创建三种方法开始。一般来说,更推荐使用命令行指令进行开发。使用命令行指令时,需要先安装nestjs-cli命令行模块。按照下述指令开始一个新的项目。


<code>#npm
npm i -g @nestjs/cli
nest new project-name
#yarn
yarn global add @nestjs/cli/<code>


使用git安装时,可通过以下命令从github上复制示例项目并在此基础上开始新项目


<code>git clone https://github.com/nestjs/typescript-starter.git project/<code>


对于高级用户来说,可能仅需要使用一部分nestjs的核心功能,在这种情况下,通过下列指令可以在项目中安装需要的模块并手动开始一个项目。


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


nestjs快速上手指南


1.2 脚手架及项目启动


安装完nestjs的命令行工具后,可通过下列命令快速搭建项目脚手架以开始新项目


<code>nest new project-name
cd project-name
npm run start
#也可以以开发模式启动项目,这样项目中任何修改和变化都可以实时编译
#在脚手架项目的package.json文件中可以看到更多的启动项目及测试的脚本命令
#npm run start:dev/<code>


通过git命令下载的项目,只要进入项目,并按照常规的nodejs项目安装模块并启动即可


<code>cd project
npm install
npm run start/<code>


运行上述命令后,打开http://localhost:3000,可以看到hello world页面。


1.3 Visual Studio Code配置Nestjs项目插件


在VS Code中进行Nestjs项目开发时,除了node环境和上述nestjs命令行工具外,可以安装以下插件来提高项目开发效率和速度。


  • nestjs Files,该插件可以实现nestjs部分生成命令的右键快捷操作。例如,如果要在一个名为cats的文件夹下新建Controller,可以在cats文件夹上点击右键,选择Generate Controller并输入Controller名称cats,就可以生成cats.controller.ts文件并在其中生成并导出CatsController类。这和Angular插件的用法非常相似,实际上相当于执行nest g controller cats或者nest g service cats命令。
  • NestJs Snippets,提供了大量的nestjs语法片段可快速使用。在命令栏Ctrl+Shift+P输入n-可以看到插件支持的大部分语法和命令。
  • REST Client。用于测试API的非常高效的VS Code插件,基本可以完全取代Postman。


2. nestjs脚手架项目


nestjs快速上手指南


除了主入口文件main.ts外,nestjs项目一般模块化组成。默认的脚手架项目包括了app.module.ts,app.controller.ts,app.service.ts几个文件。和angular项目结构类似,在nestjs项目中,controller作为控制器,一般用于处理请求并返回响应,service用来实现后台逻辑。


在controller中,使用装饰器来区分不同的路径和请求。在脚手架项目中,controller默认路径的get方法返回appService.getHello()方法,appService.getHello()方法,后者返回一个Hello World字符串。在实际项目中,这样使用同步方法来返回的情况非常少见,更多的时候都是使用异步的方法返回用户请求。以下对默认脚手架项目做一些修改,以异步的方式返回用户请求。默认脚手架项目返回如下内容:


<code>//Controller
@Get()
getHello(): string {
return this.appService.getHello();}
//Service
getHello(): string {
return 'Hello World!';
}/<code>


在app.controller.ts文件中分别做如下修改:


<code>//Controller
import { Observable,of } from 'rxjs';
getHello():Observable<string>{
return of(this.appService.getHello());
}/<string>/<code>


这里使用到了异步编程中最常用的rxjs模块中Observable和of,将字符串Hello World转换为异步对象,并返回到controller中通过async标识的异步函数中再响应给用户。虽然看到的同样是Hello World字符串,但在处理更复杂任务的时候,异步编程的优势就可以更好地显现出来。


3.通过nestjs响应网络请求


3.1 网络请求装饰器


nestjs可以通过装饰器响应不同类型的网络请求。nestjs默认启用express框架,系统提供的装饰器可以满足大部分网络请求,但也支持自定义装饰器来实现更多功能。常用的装饰器与express的对应关系列表如下:

装饰器请求@Request()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]@HttpStatus 自定义http状态


3.2 nestjs支持的一些http请求和方法:


  • nestjs支持@Put() 、 @Delete()、 @Patch()、 @Options()、 @Head()和 @All()装饰器以这些表示各自的 HTTP请求方法
  • 支持通过@HttpCode()装饰器来返回指定的状态码如201、404等(如@HttpCode(201)),需要从@nestjs/common导入。
  • 支持@Header装饰器来相应特定的header请求如@Header('Cache-Control', 'none'),同样需要从@nestjs/common导入。
  • 支持@Redirect装饰器来重定向资源例如@Redirect(http://www.weizhiyong.com`,301)。
  • 支持模式匹配通配符,例如星号(*)可以被匹配任何字符组合


3.3 路由参数


nestjs可以使用装饰器取得路由参数或http请求中的内容,一般来说,@Param参数用来读取路由参数,如https://www.weizhiyong.com/archives/:id格式的路由,在读取id参数时可以采用以下两种方式:


<code>@Controller('archives')
@Get(':id')
getId(@Param() params):string{
let result=params.id;
return result;
}
//或者
@Controller('archives')
@Get(':id')
getId(@Param('id')id):string{
return id;
}/<code>


类似地,如果要从JSON格式的Body请求中取得参数,也可以使用诸如@Body()reqbody 之类的参数进行获取。

在Controller中,也可以通过host参数添加特定的域名来访问指定值(仅适用于Express),例如.Controller({ host: 'admin.example.com' })。


4.nestjs入门示例


nestjs快速上手指南


在脚手架项目的基础上,参考官方文档,新建一个cats模块,来实现对cat的添加和基本查找功能。

在项目根目录下新建cats目录,并在其中新建cats.service.ts,cats.controller.ts和cats.module.ts文件(可以通过前节的nestjs File完成),为了实现数据接口,还需要在cats文件夹下新建dto/create-cat.dto.ts文件和interfaces/cat.interface.ts文件。


4.1 cat.interface.ts接口文件


该文件导出一个cat的接口,用于实现不同文件之间的数据交互。在实际项目中,接口文件不仅仅用于项目中不同模块之间的数据交互,也为实现前后端的统一开发提供了条件。


<code>export interface Cat{
name:string;
age:number;
breed:string;
}/<code>


4.2 create-cat.dto.ts数据传输对象(DTO)文件


在处理数据时,通常使用dto来针对不同操作指定数据接口,和interface不同,dto往往用类的方式进行声明。本文件的内容如下:


<code>export class CreateCatDto{
readonly name:string;
readonly age:number;
readonly breed:string;

}/<code>


4.3 cats.service.ts 服务器文件


服务在nestjs中被称为提供者(provider),与angular类似,provider通过注入的方式注入在controller或者module文件中以创建各种关系并执行不同功能,除了service外,其他被称为provider的类型还包括repository,factory和helper,所有的provider在nestjs中都通过@Injectable()装饰器来标识。除了@Injectable()装饰器外,提供者还支持@Optional()装饰器,来表示该provider是可选的。除了诸如某个类之外,提供者也可仅针对类中的某个属性进行诸如。本示例的文件内容如下:


<code>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);
return {'status':'ok'};
}
findAll():Cat[]{
return this.cats;
}
}/<code>


4.4 cats.controller.ts 控制器文件


控制器通过@Controller('cats')装饰器标识路径cats。通过@Post,@Get等装饰器来实现不同的http请求方法。这里使用了异步函数的实现方式,这也是nestjs中主要使用的方式。需要注意的是,异步函数可以通过Promise或者Observable两种不同方法来实现。当使用Promise时,需要用async前缀,需要Observable时,需要从rxjs中引入Observable和of。在本例中,通过@Body() createCatDto:CreateCatDto装饰器与数据传输对象从用户请求中读取数据,并保证数据格式符合要求。


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

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

@Post()
create(@Body() createCatDto:CreateCatDto):Observable{
return of(this.catsService.create(createCatDto));
}

@Get()
findAll():Observable{
return of(this.catsService.findAll());
}
// async findAll():Promise{
// return this.catsService.findAll();
// }
}
/<code>


4.5 cats.module.ts模块文件


模块文件内容如下,在模块文件中列出了本模块下的Controller和Service,如果需要引入其他模块和内容,也需要在imports中列出。如果要在模块间共享服务或者实例,也可以通过exports数组列出,例如要在其他模块中使用CatsService,可参见下文(注释掉)的exports部分代码。如果要在模块中注入提供者(比如出于配置参数的目的),也可以在模块的constructor中实现(见下列代码中注释部分)。

在nestjs中,全局模块通过@Global()装饰器标识,动态模块可以使用forRoot来同步或异步(使用Promise)返回。


<code>import { CatsService } from './cats.service';
import { CatsController } from './cats.controller';
import { Module } from '@nestjs/common';

@Module({
imports: [],
controllers: [
CatsController, ],
providers: [
CatsService, ],
//exports:[CatsService]
})
export class CatsModule {
//constructor(private readonly someService:SomeService){}

}/<code>


最后,修改app.module.ts文件以导入并使用cats模块。


<code>import { CatsModule } from './cats/cats.module';
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';

@Module({
imports: [
CatsModule, ],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}/<code>


4.6 使用REST Client客户端测试


编写一个后缀为.http的文件,就可以在nest项目运行时通过REST Client插件进行测试。在REST Client中,@用于标识变量,如以下示例中的 host 变量。 ### 用来隔开不同的命令,以保证每次执行指定的变量。可以在指令行点击指令上方的send request或者使用快捷键Ctrl+Alt+R来发送指令,并验证返回情况。


<code>@host=http://127.0.0.1:3000

###
{{host}}

###
Get {{host}}/cats
content-type: application/json

###
Post {{host}}/cats
content-type: application/json

{
"name":"Kitten1",
"age":1
}

###
Post {{host}}/cats
content-type: application/json

{
"name":"Kitten2",
"age":2
}/<code>


nestjs资源


  • nestjs英文文档
  • nestjs中文文档
  • 相关资料
    -typeorm仓库
    -Jest测试框架中文文档
    -github nest学习资源


分享到:


相關文章: