Nest.js 入门基础

2023-07-26 00:00:00

安装

# 如果是 node.js 10 之后的版本,需要加 --ignore-engines 来忽略一些不兼容库的警告
npm i -g @nestjs/cli --ignore-engines
# 或
yarn global add @nestjs/cli --ignore-engines

入门文档

小技巧

异步方法优化

减少不必要的 async/await 包裹。示例代码如下:

function test() {
  const deferred = {
    promise: undefined,
    resolve: undefined
  };
  deferred.promise = new Promise((resolve) => {
    deferred.resolve = resolve;
  });
  setTimeout(() => {
    deferred.resolve('hello world');
  }, 1000);
  return deferred.promise;
}

@Controller()
export class AppController {
  constructor(private readonly appService: AppService) {}

  // 以下两种写法都能运行,推荐使用第一种
  @Get('/test')
  getTest(): Promise<string> {
    return test();
  }

  @Get('/test2')
  async getTest2(): Promise<string> {
    return await test();
  }
}

同理,除了在 Controller 中,在 Model、 Service 等其他地方内层方法均可以进行优化,因为外层调用的时候已经带上了 await。同时,还需要注意各个方法的返回类型,养成良好习惯。

使用 Fastify 框架

该部分没有文档,只有一个示例项目: https://github.com/nestjs/nest/tree/master/sample/10-fastify

yarn remove @nestjs/platform-express
yarn remove @types/express
yarn add @nestjs/platform-fastify

修改 main.ts 文件:

import { NestFactory } from '@nestjs/core';
// 新增引用
import {
  FastifyAdapter,
  NestFastifyApplication,
} from '@nestjs/platform-fastify';
import { AppModule } from './app.module';

async function bootstrap() {
  // 原有代码:
  // const app = await NestFactory.create(AppModule);
  // 替换代码:
  const app = await NestFactory.create<NestFastifyApplication>(
    AppModule,
    new FastifyAdapter(),
  );
  await app.listen(3000);
  console.log(`Application is running on: ${await app.getUrl()}`);
}
bootstrap();

Open-API(Swagger)

目前只有英文文档,没有中文文档。地址:https://docs.nestjs.com/openapi/introduction

配合 Fastify 使用:

yarn add @nestjs/swagger
yarn add fastify-swagger
# [Nest] 7253   - 2020/07/08 下午4:42:59   [PackageLoader] The "fastify-swagger" package is missing. Please, make sure to install this library ($ npm install fastify-swagger) to take advantage of SwaggerModule. +37ms
# 如果出现类似报错,使用2.x版本重试
yarn add fastify-swagger@^2.6.0

示例代码:

import { NestFactory } from '@nestjs/core';
import {
  FastifyAdapter,
  NestFastifyApplication,
} from '@nestjs/platform-fastify';
import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
import { AppModule } from './app.module';

async function bootstrap() {
  const app = await NestFactory.create<NestFastifyApplication>(
    AppModule,
    new FastifyAdapter(),
  );
  const options = new DocumentBuilder()
    .setTitle('Cats example')
    .setDescription('The cats API description')
    .setVersion('1.0')
    .addTag('cats')
    .addBearerAuth()
    .build();
  // 生成的 JSON 格式文档,可以导出静态化
  const document = SwaggerModule.createDocument(app, options);
  // 注入, 访问 http://localhost:3000/api 可以访问
  SwaggerModule.setup('api', app, document);

  await app.listen(3000);
  console.log(`Application is running on: ${await app.getUrl()}`);
}
bootstrap();

Module 代码可以参考 Express Swagger 的示例项目: https://github.com/nestjs/nest/tree/master/sample/11-swagger

生成 Open-API.json 文件示例代码:

import { resolve } from 'path';
import { writeFileSync } from 'fs';

import { NestFactory } from '@nestjs/core';
import { FastifyAdapter, NestFastifyApplication } from '@nestjs/platform-fastify';
import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
import { AppModule } from './app.module';

async function bootstrap() {
  const app = (await NestFactory.create) < NestFastifyApplication > (AppModule, new FastifyAdapter());
  const options = new DocumentBuilder()
    .setTitle('Cats example')
    .setDescription('The cats API description')
    .setVersion('1.0')
    .addTag('cats')
    .addBearerAuth()
    .build();
  // 生成的 JSON 格式文档,可以导出静态化
  const document = SwaggerModule.createDocument(app, options);
  writeFileSync(resolve(__dirname, '../api.json'), JSON.stringify(document, null, 2), { encoding: 'utf8' });
}
bootstrap();

E2E Testing

依然没有找到文档,参考一个示例的测试源码吧: https://github.com/nestjs/nest/blob/master/integration/hello-world/e2e/fastify-adapter.spec.ts

import { Test, TestingModule } from '@nestjs/testing';
import { AppModule } from './../src/app.module';
// 新增引用
import { FastifyAdapter, NestFastifyApplication } from '@nestjs/platform-fastify';
import { expect } from 'chai';

describe('AppController (e2e)', () => {
  let app: NestFastifyApplication;

  beforeEach(async () => {
    const moduleFixture: TestingModule = await Test.createTestingModule({
      imports: [AppModule]
    }).compile();

    // 修改 app 创建
    app = moduleFixture.createNestApplication < NestFastifyApplication > new FastifyAdapter();

    await app.init();
  });

  it('/ (GET)', () => {
    // return request(app.getHttpServer())
    //   .get('/')
    //   .expect(200)
    //   .expect('Hello World!');

    // 改用 inject 方式,不用 supertest
    return app
      .inject({
        method: 'GET',
        url: '/'
      })
      .then(({ payload }) => expect(payload).to.be.eql('Hello World!'));
  });
});

Logger

npm i --save nestjs-pino
npm i --save-dev pino-pretty

main.ts 入口文件引入:

import { Logger } from 'nestjs-pino';

const app = await NestFactory.create(MyModule, { logger: false });
app.useLogger(app.get(Logger));

app.module.ts 文件引入:

import { LoggerModule } from 'nestjs-pino';

@Module({
  imports: [LoggerModule.forRoot()],
  controllers: [AppController],
  providers: [MyService]
})
class MyModule {}

Controller 中使用示例:

import { Logger } from 'nestjs-pino';

@Controller()
export class AppController {
  constructor(private readonly myService: MyService, private readonly logger: Logger) {}

  @Get()
  getHello(): string {
    // pass message
    this.logger.log('getHello()');

    // also we can pass context
    this.logger.log('getHello()', AppController.name);

    return `Hello ${this.myService.getWorld()}`;
  }
}

或者使用 PinoLogger (推荐):

// my.service.ts
import { PinoLogger, InjectPinoLogger } from 'nestjs-pino';

@Injectable()
export class MyService {
  // regular injecting
  constructor(private readonly logger: PinoLogger) {}

  // regular injecting and set context
  constructor(private readonly logger: PinoLogger) {
    logger.setContext(MyService.name);
  }

  // inject and set context via `InjectPinoLogger`
  constructor(@InjectPinoLogger(MyService.name) private readonly logger: PinoLogger) {}

  getWorld(...params: any[]) {
    this.logger.info('getWorld(%o)', params);
    return 'World!';
  }
}

启动脚本修改:

nest start --watch | pino-pretty

Graphql

依赖于apollo-server

更多推荐

【Docker】Docker简介

Docker简介📋导航1.Docker简介1.1什么是Docker?1.2什么是容器?1.3容器的优势?1.4Docker的优势?1.5虚拟技术与容器技术Docker的区别?1.6为什么学习Docker?2.安装Docker3.Docker架构4.Docker命令4.1Docker镜像(1)查看所有的镜像(2)搜索镜

学习分布式第一天(分布式系统原理和概念)

目录分布式系统原理和概念1.分布式系统:单体架构:垂直架构:分布式架构:2.分布式计算:3.CAP原理:4.BASE理论:5.Paxos算法:6.Raft算法:分布式系统原理和概念1.分布式系统:学习分布式,肯定的知道什么是分布式。分布式言简意赅,就是多台电脑部署实现你要实现的功能,突破了单机的性能机器的瓶颈(高性能)

机器学习——特征工程和评价指标

0、前言:首先学习特征工程这部分知识之前,要对机器学习的算法用过使用。1、特征工程:就机器学习的数据而言,特征就是数据的列名,有多少列,就有多少个维度的特征。就定义而言,特征是指数据中抽取出来对结果预测有用的信息。特征工程就是使用一些技巧来处理数据,使数据特征能在机器学习算法中发挥更好的作用本质而言,特征工程其实就是数

【Tensorflow 2.12 电影推荐系统之排序模型】

Tensorflow2.12电影推荐系统之排序模型学习笔记导入相关模块准备数据加载数据数据预处理获取词汇表构建模型定义评分排序模型定义损失函数以及模型评估指标定义完整的评分排序模型训练和评估创建排序模型实例缓存数据训练评估预测导出和加载模型结尾学习笔记Tensorflow2.12智能电影推荐系统搭建学习笔记~Tenso

电压放大器在电子测试中的应用有哪些方面

电压放大器是一种常见的电子设备,广泛应用于各种测试和测量应用中。以下是电压放大器在电子测试中的几个主要方面应用的简要介绍。信号采集与处理:电压放大器通常用于信号采集和处理,在测试过程中将低电平信号放大到适合进一步处理或分析的水平。例如,在生物医学领域,电压放大器常用于心电图和脑电图等生理信号的采集和放大。它们能够将微弱

单片机内存管理

源码说明源码包含memory.h和memory.c两个文件(嵌入式C/C++代码的“标配”),其源码中包含重要的注释。memory.h文件包含结构体等定义,函数API申明等;memory.c文件是实现内存管理相关API函数的原型。memory.h头文件是相关的定义和申请:#ifndef__MEMORY_H__#defi

Python爬虫实战案例——第五例

文章中所有内容仅供学习交流使用,不用于其他任何目的!严禁将文中内容用于任何商业与非法用途,由此产生的一切后果与作者无关。若有侵权,请联系删除。目标:采集三国杀官网的精美壁纸地址:aHR0cHM6Ly93d3cuc2FuZ3Vvc2hhLmNvbS9tc2dzL21XYWxsUGFwZXI=从开发者工具中进行分析可以看到

不可变集合的详细概述

1.不可变集合1.1什么是不可变集合是一个长度不可变,内容也无法修改的集合1.2使用场景如果某个数据不能被修改,把它防御性地拷贝到不可变集合中是个很好的实践。当集合对象被不可信的库调用时,不可变形式是安全的。简单理解:不想让别人修改集合中的内容比如说:1,斗地主的54张牌,是不能添加,不能删除,不能修改的2,斗地主的打

在工作流引擎设计领域,是否自动计算未来的处理人的设计模式有哪些?

概述流程的第一个节点发送下去的时候,就要把以后所有节点的处理人计算出来,能清楚的知道每个节点都是那些人处理.以驰骋bpm为例来说明这个设计计算未来处理人包括抄送节点、与待办节点.默认的模式为:每个节点发送的时候即使计算,就是不计算未来处理人.流程设计特征.流程的所有节点的接受人不能是主管选择的,只能是自动计算.节点的转

SpringBoot之yaml

文章目录前言一、基本语法二、数据类型介绍实例三、配置提示总结前言YAML是“YAMLAin’tMarkupLanguage”(YAML不是一种标记语言)的递归缩写。在开发的这种语言时,YAML的意思其实是:“YetAnotherMarkupLanguage”(仍是一种标记语言)。非常适合用来做以数据为中心的配置文件。一

奥特曼与钢铁侠【InsCode Stable Diffusion美图活动一期】

文章目录简介图片生成步骤更多体验方式简介InsCode是一个一站式的软件开发服务平台,从开发-部署-运维-运营,都可以在InsCode轻松完成。InsCode的Ins是Inspiration,意思是创作、寻找有灵感的代码。StableDiffusion是文图生成模型,也可以理解成是AI动画生成工具。在线运行地址:htt

热文推荐