当前位置 : 主页 > 手机教程 > 手机资讯 >

Nest.js快速启动API项目过程详解

来源:互联网 收集:自由互联 发布时间:2023-01-20
目录 快速启动 使用nest自带的命令行工具 直接使用starter项目 用npm安装所需的包 创建controller 创建service 结构和命名 HTTP请求 处理Axios对象 配置 全局添加headers API文档 快速启动 最近上了
目录
  • 快速启动
    • 使用nest自带的命令行工具
    • 直接使用starter项目
    • 用npm安装所需的包
    • 创建controller
    • 创建service
  • 结构和命名
    • HTTP请求
      • 处理Axios对象
    • 配置
      • 全局添加headers
    • API文档

      快速启动

      最近上了一个新项目,这个客户管理一个庞大的任务和团队集群,而不同流程所适用的系统也不太一样,比如salesforce,hubspots之类的。这次的新项目需要在另外两个平台之间做一些事情。目前只需要先封装其中之一的API,因此我们选定使用NodeJS的框架Nest.js来实现这套API。

      开启nestjs项目有3种便捷的方式。

      使用nest自带的命令行工具

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

      即使不使用这种方式,也建议在node全局安装命令行工具,这样可以方便的生成各种nestjs的模块,比如controller和service之类的。

      直接使用starter项目

      这里还有一个用于启动的样例项目,可以直接使用。

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

      而且这个项目还附带了Typescript。不过要记得把之前的git信息删掉。

      用npm安装所需的包

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

      直接安装nestjs的core和common就可以,rxjs和reflext-metadata也是必需的。

      这种方式比较干净,目录什么的需要自己创建。不过也可以使用命令行创建controller之类的,目录会自动创建好。

      总的来说,nestjs和其他语言API框架类似,很多东西可以自动生成或者无需编写,所以约定的习惯非常重要,尽量不要创建一些“独特”的结构,避免以后踩坑。

      创建controller

      创建好项目之后,我创建了一个controller,nest.js中controller可以通过修饰器直接提供路由,因此没有一个route之类的文件用于配置。

      nest g controller projects

      nest.js的目录约定是按业务模块划分,因为src目录中会出现一个projects的目录,该目录下会生成一个projects.controller,以及附带的单元测试。

      创建service

      接着创建service,用于封装目标任务管理平台关于Projects的API。

      nest g service projects

      创建controller和service都会自动加入到module里,可以在每次生成后用git diff查看一下生成了哪些代码,也好心理有数。

      import { Controller, Get, Req } from '@nestjs/common';
      import { Request } from 'express';
      import { Project } from 'src/interfaces/project.interface';
      import { ProjectsService } from './projects.service';
      @Controller('projects')
      export class ProjectsController {
      constructor(private projectsService: ProjectsService) {}
      @Get()
      findAll(@Req() request: Request): Project[] {
      return this.projectsService.findAll();
      }
      }
      import { Injectable } from '@nestjs/common';
      import { Project } from 'src/interfaces/project.interface';
      @Injectable()
      export class ProjectsService {
      findAll(): Project[] {
      return [];
      }
      }

      结构和命名

      另外我特别想说明一下的是,虽然我为controller和service都使用了相同的名称,但并不是说他们是一一对应的。很多项目只是为了分层而分,controller和service都是一一对应的,其实并不正确。分层是因为它们拥有不同的意义,只有明确语义,才能在思维的过程中更好的掌握代码,也可以更好的复用,层次起到的是一种认知转换的作用。如果只是把底层的对象毫无变化的映射出来,那这个过程是毫无意义的。

      这里的service在nestjs中其实是provider的一种,而provider的意义则是从各种不同的地方提供数据或其他东西。我使用的ProjectsService意义在于封装另一个API,所以这个projects来源于目标任务管理平台的API名称。而controller的名称projects指的是我创建的API所要提供的数据是project,只不过它们在这里确实是同一个东西,所以名称也一样。

      假设,现在的业务逻辑是需要从目标任务管理平台获取projects,之后过滤出两种不同特性的projects,一种叫task任务,需要分配给人员;另一种叫note记录,只是标记一下。它们拥有不同的特性。那么我就会创建2个controller,taskController和noteController,但是它们都调用ProjectsService去使用不同的过滤条件获取数据。

      HTTP请求

      使用nest.js官方的Http模块HttpModule就可以向其他API发出请求。该模块其实也是封装的Axios,所以用起来很方便。先安装相关模块。

      npm i --save @nestjs/axios axios

      然后在app.module中引入。

      import { HttpModule } from '@nestjs/axios';
      ...
      @Module({
      imports: [HttpModule], // 引入Http模块
      controllers: [ProjectsController],
      providers: [ProjectsService],
      })
      export class AppModule {}

      处理Axios对象

      在service中可以这样处理http请求的返回值。

      import { HttpService } from '@nestjs/axios';
      import { Injectable } from '@nestjs/common';
      import { map, Observable } from 'rxjs';
      import { Project } from 'src/interfaces/project.interface';
      import { AxiosResponse } from 'axios';
      @Injectable()
      export class ProjectsService {
      constructor(
      private readonly httpService: HttpService
      ) {}
      findAll(): Observable<Project[]> {
      return this.httpService.get('http://localhost:3000/api-json').pipe(
      map((axiosResponse: AxiosResponse) => {
      return axiosResponse.data;
      })
      );
      }
      }

      因为Axios会包裹一层,用data作为统一的key,所以需要map出来。这里的pipe和map方法都是来自rxjs。rxjs的核心就是Observable,使用响应式编程的方式,封装了回调和异步方式的代码。因此这里你看不到promise或者await/async之类的关键字。

      配置

      上面的请求,我只是使用了一个本地的json接口用于测试。要真正的调用目标平台的API,还需要配置项,因为包括API token这种重要字符串的一些值,需要放在环境变量中,不能直接放在代码被git提交。

      所以我需要加上config的配置,安装nest.js的config包,它封装的其实是dotenv包,经常使用nodejs的话,应该会很熟悉这个包。

      npm i --save @nestjs/config

      同样在app.module中引入config模块。

      import { ConfigModule } from '@nestjs/config';
      import configuration from './config/configuration';
      ...
      imports: [
      HttpModule,
      ConfigModule.forRoot({
      load: [configuration],
      })
      ],
      ...

      这里使用forRoot是因为该模块是单例模式的。而传入的参数load可以把config对象载入。

      引入的config/configuration文件是新创建的配置对象。

      export default () => ({
      port: parseInt(process.env.PORT, 10) || 3000,
      runn: {
      url: process.env.RUNN_API_URL,
      token: process.env.RUNN_API_TOKEN
      }
      });

      我配置了端口,以及API的URL和Token。

      然后可能需要用到Typescript的接口,可以使用nest生成文件。

      nest g interface runn-config
      export interface RunnConfig {
      url: string
      token: string
      }

      在service中就可以获取这些配置项。

      import { ConfigService } from '@nestjs/config';
      import { RunnConfig } from 'src/interfaces/runn-config.interface';
      ...
      constructor(
      private readonly httpService: HttpService,
      private configService: ConfigService
      ) {}
      ...
      const config = this.configService.get<RunnConfig>('runn');

      ... const config = this.configService.get<RunnConfig>('runn');

      不要忘记在根目录下创建.env文件填入配置的值。另外按习惯,可以创建.env.sample文件,只包含key,没有值,类似模板,被git提交管理。而.env文件则被gitignore。只在本地保留。在服务器上需要另外生成一份。

      全局添加headers

      URL使用了,但Token需要在headers中添加。在app.module中使用HttpModule的register方法就可以配置其中封装的Axios。不过由于token来自config,所以需要用比较麻烦的registerAsync,注入config后,在useFactory中使用。

      ...
      imports: [
      HttpModule.registerAsync({
      imports: [ConfigModule],
      inject: [ConfigService],
      useFactory: (configService: ConfigService) => ({
      headers: {
      'Content-Type': 'application/json',
      Authorization: 'Bearer ' + configService.get('runn.token')
      }
      })
      }),
      ...
      ],
      ...

      这样我就创建了一个基本API框架,并请求了一个简单的目标任务管理系统的API获取数据。

      API文档

      另外,由于客户需要了解和测试我们的API,所以需要一个postman的api集合。我准备使用Swagger,这是一个API文档的自动生成工具,它会根据框架中定义的API和参数,自动生成一个页面,包含所有的API和参数说明,以及可以直接请求该API。当然这需要修饰器的辅助。先安装nestjs的swagger包。

      npm i --save @nestjs/swagger

      然后在main.ts中引入并配置。

      import { NestFactory } from '@nestjs/core';
      import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger';
      import { AppModule } from './app.module';
      async function bootstrap() {
      const app = await NestFactory.create(AppModule);
      // swagger
      const config = new DocumentBuilder()
      .setTitle('My APIs')
      .setDescription('My APIs documents')
      .setVersion('1.0')
      .build();
      const document = SwaggerModule.createDocument(app, config);
      SwaggerModule.setup('api', app, document);
      // swagger end
      await app.listen(3000);
      }
      bootstrap();
      

      然后就可以通过http://localhost:3000/api访问该API文档页面。不过目前所有API都会出现在default默认标签下。官方示例中使用的addTag方法虽然可以添加一个标签,但并不能指定某些API放入该标签。我需要通过修饰器实现。

      在controller的方法上使用@ApiTags('Project')即可,该方法会被放置在Project标签下。

      除了API文档的页面形式。http://localhost:3000/api-json的JSON格式才是最重要的,可以使用它在Postman中直接导入。

      以上就是Nest.js快速启动API项目过程详解的详细内容,更多关于Nest.js快速启动API的资料请关注自由互联其它相关文章!

      上一篇:使用KrpanoToolJS在浏览器切图的实例详解
      下一篇:没有了
      网友评论