Skip to content
On this page

NestJS基础概念

NestJS是一个渐进式的Node.js框架,用于构建高效、可扩展的服务端应用程序。它结合了OOP、FP和FRP的元素,深受Angular的启发。

核心架构

依赖注入 (Dependency Injection)

NestJS使用内置的依赖注入系统来管理类之间的依赖关系。

typescript
import { Injectable } from '@nestjs/common';

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

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

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

在控制器中注入服务:

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

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

  @Post()
  async create(@Body() createCatDto: Cat) {
    this.catsService.create(createCatDto);
  }

  @Get()
  async findAll(): Promise<Cat[]> {
    return this.catsService.findAll();
  }
}

装饰器 (Decorators)

NestJS使用装饰器来添加元数据到类和方法:

typescript
import { 
  Controller, 
  Get, 
  Post, 
  Put, 
  Delete, 
  Param, 
  Body, 
  Query,
  Headers,
  Req,
  Res 
} from '@nestjs/common';
import { Request, Response } from 'express';

@Controller('users')
export class UsersController {
  // GET请求
  @Get()
  findAll(@Query() query: any) {
    return `Returning all users with query: ${JSON.stringify(query)}`;
  }

  // GET请求带参数
  @Get(':id')
  findOne(@Param('id') id: string, @Headers('authorization') auth: string) {
    return `Returning user with id: ${id}, auth: ${auth}`;
  }

  // POST请求
  @Post()
  create(@Body() createUserDto: any) {
    return `Creating user with data: ${JSON.stringify(createUserDto)}`;
  }

  // 使用原生请求和响应对象
  @Get('raw/:id')
  findOneRaw(@Param('id') id: string, @Req() req: Request, @Res() res: Response) {
    res.status(200).send(`User ID: ${id}`);
  }
}

模块系统

模块定义

模块是带有@Module()装饰器的类,它定义了应用程序的结构:

typescript
import { Module } from '@nestjs/common';
import { CatsController } from './cats/cats.controller';
import { CatsService } from './cats/cats.service';
import { CatsModule } from './cats/cats.module';

@Module({
  imports: [CatsModule], // 导入其他模块
  controllers: [CatsController], // 该模块的控制器
  providers: [CatsService], // 该模块的服务
  exports: [CatsService], // 导出供其他模块使用的提供者
})
export class AppModule {}

功能模块

typescript
// cats/cats.module.ts
import { Module } from '@nestjs/common';
import { CatsController } from './cats.controller';
import { CatsService } from './cats.service';

@Module({
  controllers: [CatsController],
  providers: [CatsService],
  exports: [CatsService], // 导出服务供其他模块使用
})
export class CatsModule {}

共享模块

typescript
// database/database.module.ts
import { Module } from '@nestjs/common';
import { DatabaseService } from './database.service';

@Module({
  providers: [DatabaseService],
  exports: [DatabaseService],
})
export class DatabaseModule {}

控制器 (Controllers)

控制器负责处理传入的请求并返回响应给客户端。

typescript
import { 
  Controller, 
  Get, 
  Post, 
  Body, 
  Param, 
  Query,
  Put,
  Delete,
  HttpStatus,
  HttpCode,
  Header,
  Redirect,
  Render,
  Res,
  UseInterceptors
} from '@nestjs/common';
import { Response } from 'express';
import { CatsService } from './cats.service';

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

  @Get()
  @HttpCode(HttpStatus.OK)
  @Header('Cache-Control', 'none')
  findAll(): string {
    return 'This action returns all cats';
  }

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

  @Get(':id')
  @Render('cats')
  findOne(@Param('id') id: string) {
    return { id: id };
  }

  @Post()
  @UseInterceptors(SomeInterceptor)
  create(@Body() createCatDto: any) {
    return this.catsService.create(createCatDto);
  }

  @Get('stream')
  stream(@Res() res: Response) {
    res.setHeader('Content-Type', 'text/plain');
    res.status(HttpStatus.OK);
    res.send('Streamed response');
  }
}

提供者 (Providers)

提供者是NestJS的基本构建块,包括服务、仓库、工厂、助手等。

服务提供者

typescript
import { Injectable, Scope } from '@nestjs/common';

@Injectable()
export class CatsService {
  constructor() {}

  getHello(): string {
    return 'Hello from CatsService';
  }
}

// 请求范围的提供者
@Injectable({ scope: Scope.REQUEST })
export class RequestScopedService {
  constructor() {}
}

工厂提供者

typescript
import { Injectable } from '@nestjs/common';

@Injectable()
export class ConfigService {
  get(key: string): string {
    return process.env[key];
  }
}

// 工厂提供者
export const configProvider = {
  provide: 'CONFIG_SERVICE',
  useFactory: (configService: ConfigService) => {
    return {
      port: configService.get('PORT') || 3000,
      host: configService.get('HOST') || 'localhost',
    };
  },
  inject: [ConfigService],
};

别名提供者

typescript
export const loggerAliasProvider = {
  provide: 'CUSTOM_LOGGER',
  useExisting: 'LOGGER',
};

生命周期钩子

NestJS提供了一些生命周期钩子,允许您在特定时间点执行代码:

typescript
import { Injectable, OnModuleInit, OnModuleDestroy, OnApplicationBootstrap } from '@nestjs/common';

@Injectable()
export class CatsService implements OnModuleInit, OnModuleDestroy, OnApplicationBootstrap {
  async onModuleInit() {
    console.log('Module initialized.');
  }

  async onApplicationBootstrap() {
    console.log('Application is bootstrapped.');
  }

  async onModuleDestroy() {
    console.log('Module destroyed.');
  }
}

异步模块初始化

typescript
import { Module, DynamicModule } from '@nestjs/common';
import { DatabaseModule } from './database/database.module';
import { ConfigModule } from './config/config.module';

@Module({
  imports: [DatabaseModule],
})
export class AppModule {
  static async forRoot(): Promise<DynamicModule> {
    const configService = new ConfigService();
    await configService.loadConfig(); // 异步加载配置

    return {
      module: AppModule,
      imports: [
        DatabaseModule.forRoot(configService.getDatabaseConfig()),
        ConfigModule,
      ],
      providers: [
        {
          provide: 'CONFIG_SERVICE',
          useValue: configService,
        },
      ],
      exports: ['CONFIG_SERVICE'],
    };
  }
}

作用域和注入范围

typescript
import { Injectable, Scope } from '@nestjs/common';

// 默认是单例
@Injectable()
export class CatsService {}

// 请求范围 - 每个请求创建一个实例
@Injectable({ scope: Scope.REQUEST })
export class RequestService {
  private readonly id = Math.random();
  
  getId() {
    return this.id;
  }
}

// 过渡范围
@Injectable({ scope: Scope.TRANSIENT })
export class TransientService {
  private readonly id = Math.random();
  
  getId() {
    return this.id;
  }
}

自定义提供者

typescript
// 值提供者
export const connectionProvider = {
  provide: 'CONNECTION',
  useValue: {
    host: 'localhost',
    port: 5432,
  },
};

// 类提供者
export const loggerProvider = {
  provide: 'LOGGER',
  useClass: CustomLogger,
};

// 工厂提供者
export const httpProvider = {
  provide: 'HTTP_SERVICE',
  useFactory: (configService: ConfigService) => {
    const isDev = configService.get('ENV') === 'development';
    return isDev ? new DevHttpService() : new ProductionHttpService();
  },
  inject: [ConfigService],
};

应用程序上下文

typescript
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';

async function bootstrap() {
  // 创建应用实例
  const app = await NestFactory.create(AppModule);
  
  // 设置全局前缀
  app.setGlobalPrefix('api');
  
  // 启用CORS
  app.enableCors();
  
  // 启用热重载
  if (process.env.NODE_ENV === 'development') {
    app.enableShutdownHooks();
  }
  
  // 监听端口
  await app.listen(3000);
}
bootstrap();

这些基础概念构成了NestJS的核心,理解它们对于构建复杂的应用程序至关重要。