从0到1深入浅出构建Nest.Js项目

Nest (NestJS) 是一个用于构建高效、可扩展的 Node.js 服务器端应用程序的开发框架。它利用JavaScript 的渐进增强的能力,使用并完全支持 TypeScript (仍然允许开发者使用纯 JavaScript 进行开发),并结合了 OOP (面向对象编程)、FP (函数式编程)和 FRP (函数响应式编程)。

在底层,Nest 构建在强大的 HTTP 服务器框架上,例如 Express (默认),并且还可以通过配置从而使用 Fastify

Nest 在这些常见的 Node.js 框架 (Express/Fastify) 之上提高了一个抽象级别,但仍然向开发者直接暴露了底层框架的 API。这使得开发者可以自由地使用适用于底层平台的无数的第三方模块。

NestJS 是一个基于 TypeScript 的服务器端应用程序框架。 它提供了一组丰富的工具和模块来帮助开发人员构建高效、可扩展的服务器端应用程序。这些元素可以通过依赖注入系统自动注册,并可以在整个应用程序中共享

总的来说,NestJS 是一个功能丰富、易于使用的服务器端应用程序框架,可帮助开发人员快速构建高效、可扩展的服务器端应用程序。

一、NestJS优势

NestJS 的一些优势包括:

  • 构建在现代 JavaScript 栈之上,因此使用了最新的 JavaScript 技术。
  • 基于 Angular 的架构和语法,提供了强大的模块化系统和依赖注入功能。
  • 基于 TypeScript,提供了强类型和静态类型检查。
  • 提供了丰富的工具和模块,可用于构建各种类型的服务器端应用程序,包括 RESTful API、GraphQL API、WebSocket 服务器等。
  • 提供了一组可扩展的构建块,可用于快速构建应用程序。
  • 提供了与主流数据库和身份验证系统的集成。

二、IOC(控制反转 )和依赖注入DI概念

这两个概念不要搞混了,IOC其实是面向对象编程中的一种设计模式,而DI则是为了实现IOC的一种技术。

下面简单认识一下为什么需要IOC,IOC有什么好处,简单来说就是减少了固定性,通过外部传参进行控制内部本身固定的一些变量,如下例子:

在我们的代码中,经常会出现一个类依赖于另外一个类的情况,比如这样:

class Dog {
   }

class Person {
   
  private _pet

  constructor () {
   
    this._pet = new Dog()
  }
}

const xiaoming = new Person()

当我们遇到类与类之间存在依赖关系时,一般会直接在类的内部创建依赖对象,这样就会导致各个类之间形成耦合,并且这种关系会随着依赖关系越来越复杂从而耦合度也会越来越高,最终造成代码的难以维护。

在上述例子中:

  • Person类固定依赖于Dog类,如果后续Person想要依赖于其他宠物类,是无法轻易修改的。
  • 并且如果Dog类有所变化,比如其属性颜色染成了黑色,Person类也会直接受到影响。

IOC的思想就是将类的依赖动态注入,以解决上述两个问题:

class Dog {
   }

class Person {
   
  private _pet

  constructor (pet) {
   
    this._pet = pet
  }
}

const xiaohei = new Dog()
const xiaoming = new Person(xiaohei) // 将实例化的 dog 传入 person 类

这样,我们就实现了类的控制反转,同时,我们需要有一个容器来维护各个对象实例,当用户需要使用实例时,容器会自动将对象实例化给用户,这部分通常由框架处理。

这种动态注入的思想叫做依赖注入(DI, Dependency Injection),它是 IoC 的一种应用形式,把对象或依赖的实例化交给IOC容器去处理,在NestJS中这个容器就是NestJS的运行时系统。当需要一个对象实例的时候,我们不需要自己手动new xxxClass(),只需要在合适的地方对类进行注册,在需要用到的地方直接注入,容器将为我们完成new的动作。

三、NestJs中使用方式

Nest中使用依赖注入一般有以下三步:

1、声明定义

使用@Injectable装饰器来声明一个类,它表示该类可以由NestIOC容器管理

通常命名方式为XXX.service.ts

// app.service.ts
import {
    Injectable } from '@nestjs/common';

@Injectable()
export class AppService {
   
  getHello(): string {
   
    return 'Hello jiusi';
  }
}

2、声明在什么地方使用

这是依赖注入的地方,一般是在类的构造函数constructor中注入,只有完成注入后才可以使用

// app.controller.ts
import {
    Controller, Get } from '@nestjs/common';
import {
    AppService } from './app.service';

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

  @Get('/hello')
  get(): string {
   
    return this.appService.getHello();
  }
}

官方把appService称为tokenNestJS会根据这个token在容器中找到第1步中声明的类(这个对应关系将在第三步中进行关联注册),从而提供对应的实例,这里的实例全局唯一,只有1个!在第一次需要该实例的时候,Nestnew一个出来,而后会缓存起来,后序如果其它地方也注入了这个依赖,那Nest会从缓存中拿到之前new出来的实例供大家使用。

3、建立注入依赖与容器中类的联系

依赖注入后还需要在Module中进行关联

import {
    Module } from '@nestjs/common';
import {
    AppController } from './app.controller';
import {
    AppService } from './app.service';

@Module({
   
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {
   }

Nest会根据所有注入的依赖关系生成一个依赖关系图,就有点类似我们使用import引入各个模块时也会生成一个复杂的依赖关系图。这里AppController中依赖了AppService,如果AppService中还依赖其它东西也会一并放到Nest构建的依赖关系图中,Nest会从下到上按照依赖顺序构建出一整张依赖关系图保证所有的依赖关系正常运作。

四、AOP(Aspect Oriented Programming)

中文为面向切面编程。当一个请求打过来时,一般会经过 Controller(控制器)、Service(服务)、Repository(数据库访问) 的链路。当我们不使用AOP时,需要添加一些通用逻辑时(如日志记录、权限守卫、异常处理等等),就需要在每段请求逻辑中编写相关代码。

AOP就是在所有请求外面包裹一层切面,所有请求都会经过这个切面,然后我们就可以把上述的通用逻辑放在这个结构里,如下图:

在这里插入图片描述

在nestJS中实现AOP的方式有很多,比如(excepion filter过滤器、pipes管道、guards守卫、interceptors拦截器)。

五、NestJS请求流程图

  • Controllers -> 处理请求
  • Service -> 数据访问与核心逻辑
  • Modules -> 组合所有的逻辑代码
  • Pipes -> 管道–核验请求的数据
  • Filters -> 过滤器–处理请求时的错误
  • Guards -> 守卫–鉴权与认证
  • Interceptors -> 拦截器-给请求与响应加入额外的逻辑
  • Repositories -> 处理在数据库中数据

六、构建NestJs实际项目

在这里插入图片描述

1、项目创建

首先确定你已经安装了Node.js, Node.js 安装会附带npx和一个npm 包运行程序。要创建新的Nest.js 应用程序,请在终端上运行以下命令:

npm i -g @nestjs/cli  // 全局安装Nest
nest new project-name  // 创建项目

执行完创建项目, 会初始化下面这些文件, 并且询问你要是有什么方式来管理依赖包。

如果你有安装yarn,可以选择yarn,能更快一些。

注意: Nest.js 要求 Node.js(>= 10.13.0,v13 除外), 如果你的Node.js 版本不满足要求,可以通过nvm包管理工具安装符合要求的Node.js版本

2、项目结构

src
├── app.controller.spec.ts
├── app.controller.ts
├── app.module.ts
├── app.service.ts
├── main.ts
app.controller.ts 单个路由的基本控制器(Controller)
app.controller.spec.ts 针对控制器的单元测试
app.module.ts 应用程序的根模块(Module)
app.service.ts 具有单一方法的基本服务(Service)
main.ts 应用程序的入口文件,它使用核心函数 NestFactory 来创建 Nest 应用程序的实例。

3、第一个接口

前面我们已经启动了服务, 那我们怎么查看呢, 首先就是找到入口文件main.ts

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

async function bootstrap() {
   
  const app = await NestFactory.create(AppModule);
  await app.listen(3000);
}
bootstrap();

内容比较简单, 使用Nest.js的工厂函数NestFactory来创建了一个AppModule实例,启动了 HTTP 侦听器,以侦听main.ts 中所定义的端口。

监听的端口号可以自定义, 如果3000端口被其他项目使用,可以更改为其他的端口号

前边看到main.ts中也没有别的文件引入, 只有AppModule, 打开src/app.module.ts:

import {
    Module } from '@nestjs/common';
import {
    AppController } from './app.controller'
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值