大家好,我是water,欢迎关注我的公众号:前端进阶说,最近在看Nestjs相关内容就做个学习记录,希望对你有帮助。
前言
nest服务中,其实和前端开发中类似,也是拥有生命周期的。服务在一个生命周期中结束,中间会涉及到中间件、守卫等,最后经过控制器和服务处理然后返回到前端,这样一个请求的服务生命周期结束。而且在nest中还有一些开发的核心概念和范式,这些对于一些不是后端的小伙伴非常重要,这里本着学习的态度对这些温习一下。

nest中涉及的编程范式
OOP
面向对象编程(OOP)是一种编程范式,它将数据和操作数据的方法组合在一起,以便将对象视为单个实体。对象的设计包括属性和方法,属性是对象的特征,而方法是对象的行为。OOP的主要优点是代码重用性、灵活性和可维护性。
OOP的四个基本概念是:
- 封装(
Encapsulation):将数据和方法组合在一起,以便将对象视为单个实体,并保护其内部状态。封装可以防止外部代码直接访问对象的数据,从而提高了代码的安全性和可维护性。 - 继承(
Inheritance):允许创建一个新类,该类从现有类继承属性和方法。继承可以减少代码重复,并使代码更易于维护。 - 多态(
Polymorphism):允许使用相同的方法来处理不同类型的对象。多态可以提高代码的灵活性和可扩展性。 - 抽象(
Abstraction):将复杂的现实世界建模为类和对象,以便更好地理解和管理代码。抽象可以隐藏对象的复杂性,并使代码更易于理解和维护。
在js中所有东西都是对象,包括数字、字符串、函数和类。js支持OOP,因此可以使用类和对象来编写面向对象的代码。
FP
函数式编程(FP)是一种编程范式,它将计算视为数学函数的求值,并避免使用可变状态和可变数据。FP的主要优点是代码可读性、可维护性和可扩展性。
FP的基本概念是:
- 纯函数(
Pure Function):不依赖于外部状态或数据的函数,其输出仅由输入决定。纯函数可以避免副作用和不可预测性,并提高代码的可读性和可维护性。 - 不可变性(
Immutability):避免使用可变状态和可变数据,以便更好地控制代码的行为和状态。不可变性可以提高代码的可读性、可维护性和可扩展性。 - 高阶函数(
Higher-Order Function):接受一个或多个函数作为参数或返回一个函数的函数。高阶函数可以提高代码的抽象级别和可复用性。
在js中,函数是一等公民,可以像其他对象一样传递和操作。js支持FP,因此可以使用函数和高阶函数来编写函数式的代码。
FRP
函数响应式编程(Functional Reactive Programming,FRP)是一种编程范式,它结合了函数式编程和响应式编程的概念。FRP的主要思想是将数据流看作是连续的时间变化的信号,并使用函数来处理这些信号。FRP的主要优点是代码可读性、可维护性和可扩展性。在js中,可以使用第三方库Rxjs来实现FRP。
AOP
AOP(Aspect-Oriented Programming)是一种编程范式,它的主要思想是将程序的功能分解成不同的关注点(Aspect),然后通过横向切割(Cross-Cutting Concerns)的方式将这些关注点分离出来。AOP的主要优点是代码可读性、可维护性和可扩展性。使用AOP的好处是:
-
在业务外增加新功能,解耦
-
扩展功能方便,不影响业务之间的逻辑
-
逻辑集中管理
-
更有利于代码的复用
-
AOP能在不破坏封装功能的前提下,额外增加功能
IOC
控制反转(Inversion of Control,IoC)是一种编程思想,它的主要思想是将程序的控制权从程序代码中转移到外部容器中,由容器来管理程序的生命周期和依赖关系。IoC的主要优点是代码可读性、可维护性和可扩展性。
IOC是一种思想&设计模式
DI
依赖注入(Dependency Injection,DI)是一种编程思想,它的主要思想是将程序的依赖关系从程序代码中移除,由外部容器来管理程序的依赖关系。DI的主要优点是代码可读性、可维护性和可扩展性。
DI是IOC的具体实现
控制反转是一种面向对象编程中的一种设计原则,用来减低计算机代码之间的耦合度,其基本思想是:借助于“第三方”实现具有依赖关系的对象之间的解耦
依赖注入是一种用于实现ioc的设计模式,它允许类外创建依赖对象,并通过不同的方式将这些对象提供给类。
nest生命周期

nest核心概念
中间件
NestJS中的中间件是一种用于处理HTTP请求的函数,它可以在请求到达控制器之前或之后执行一些操作。中间件可以用于实现身份验证、日志记录、错误处理等功能。在NestJS中,中间件可以是全局的,也可以是局部的。以下是一个中间件的示例代码:
import { Injectable, NestMiddleware } from '@nestjs/common';
import { Request, Response } from 'express';
@Injectable()
export class LoggerMiddleware implements NestMiddleware {
use(req: Request, res: Response, next: Function) {
console.log('Request...');
next();
}
}
在上面的代码中,我们定义了一个名为LoggerMiddleware的中间件类,它实现了NestMiddleware接口。在use()方法中,我们打印了一条日志,并调用了next()函数,表示请求可以继续向下执行。要在应用程序中使用中间件,我们需要将其添加到模块或控制器中。以下是一个将中间件添加到模块中的示例代码:
import { Module, NestModule, MiddlewareConsumer } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { LoggerMiddleware } from './logger.middleware';
@Module({
imports: [],
controllers: [AppController],
providers: [AppService],
})
export class AppModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
consumer
.apply(LoggerMiddleware)
.forRoutes('*');
}
}
在上面的代码中,我们将LoggerMiddleware中间件添加到了AppModule模块中,并使用forRoutes('*')方法指定了该中间件适用于所有路由。这样,每次请求到达控制器之前,都会先执行LoggerMiddleware中间件中的代码。
守卫
NestJS中的守卫(Guard)是一种用于保护路由的机制,它可以在请求到达控制器之前或之后执行一些操作。守卫可以用于实现身份验证、权限控制、缓存等功能。在NestJS中,守卫可以是全局的,也可以是局部的。以下是一个守卫的示例代码:
import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common';
import { Observable } from 'rxjs';
@Injectable()
export class AuthGuard implements CanActivate {
canActivate(
context: ExecutionContext,
): boolean | Promise<boolean> | Observable<boolean> {
const request = context.switchToHttp().getRequest();
return validateRequest(request);
}
}
function validateRequest(request: Request): boolean {
// 验证请求是否合法
return true;
}
在上面的代码中,我们定义了一个名为AuthGuard的守卫类,它实现了CanActivate接口。在canActivate()方法中,我们获取了请求对象,并调用了validateRequest()函数来验证请求是否合法。如果请求合法,就返回true,否则返回false。要在控制器中使用守卫,我们需要将守卫添加到路由上。以下是一个将守卫添加到路由上的示例代码:
import { Controller, Get, UseGuards } from '@nestjs/common';
import { AuthGuard } from './auth.guard';
@Controller()
export class AppController {
@Get()
@UseGuards(AuthGuard)
getHello(): string {
return 'Hello World!';
}
}
在上面的代码中,我们将AuthGuard守卫添加到了路由上,并使用@UseGuards()装饰器来指定守卫的类名。这样,每次请求到达控制器之前,都会先执行AuthGuard守卫中的代码,以确保请求的合法性。
拦截器
NestJS中的拦截器(Interceptor)是一种用于处理HTTP请求和响应的函数,它可以在请求到达控制器之前或之后执行一些操作。拦截器可以用于实现日志记录、错误处理、数据转换等功能。在NestJS中,拦截器可以是全局的,也可以是局部的。以下是一个拦截器的示例代码:
import { Injectable, NestInterceptor, ExecutionContext, CallHandler } from '@nestjs/common';
import { Observable } from 'rxjs';
import { tap } from 'rxjs/operators';
@Injectable()
export class LoggingInterceptor implements NestInterceptor {
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
console.log('Before...');
const now = Date.now();
return next
.handle()
.pipe(
tap(() => console.log(`After... ${Date.now() - now}ms`)),
);
}
}
在上面的代码中,我们定义了一个名为LoggingInterceptor的拦截器类,它实现了NestInterceptor接口。在intercept()方法中,我们打印了一条日志,并记录了当前时间。然后,我们调用了next.handle()函数,表示请求可以继续向下执行。在请求处理完成后,我们又打印了一条日志,并计算了请求处理的时间。要在应用程序中使用拦截器,我们需要将其添加到模块或控制器中。以下是一个将拦截器添加到模块中的示例代码:
import { Module, NestModule, MiddlewareConsumer } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { LoggingInterceptor } from './logging.interceptor';
@Module({
imports: [],
controllers: [AppController],
providers: [AppService],
})
export class AppModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
consumer
.apply(LoggerMiddleware)
.forRoutes('*');
}
}
controller
NestJS中的控制器(Controller)是用于处理HTTP请求的类,它们负责处理来自客户端的请求并返回响应。控制器可以使用装饰器(Decorator)来定义路由、请求方法、中间件等。在NestJS中,控制器是一个普通的类,它可以使用依赖注入(Dependency Injection)来获取其他服务(Service)的实例。以下是一个控制器的示例代码:
import { Controller, Get } from '@nestjs/common';
import { AppService } from './app.service';
@Controller()
export class AppController {
constructor(private readonly appService: AppService) {}
@Get()
getHello(): string {
return this.appService.getHello();
}
}
在上面的代码中,我们定义了一个名为AppController的控制器类,它使用了@Controller()装饰器来定义路由。在构造函数中,我们使用了依赖注入来获取AppService的实例。在getHello()方法中,我们调用了AppService的getHello()方法并返回了它的返回值。
service
service层负责提供方法和操作,只包含业务逻辑
NestJS中的服务(Service)是用于处理业务逻辑的类,它们负责处理控制器(Controller)发来的请求并返回响应。服务可以使用依赖注入(Dependency Injection)来获取其他服务的实例。在NestJS中,服务是一个普通的类,它可以使用@Injectable()装饰器来标记自己是一个服务。以下是一个服务的示例代码:
import { Injectable } from '@nestjs/common';
@Injectable()
export class AppService {
getHello(): string {
return 'Hello World!';
}
}
在上面的代码中,我们定义了一个名为AppService的服务类,它使用了@Injectable()装饰器来标记自己是一个服务。在getHello()方法中,我们返回了一个字符串'Hello World!'。在控制器中,我们可以使用依赖注入来获取AppService的实例并调用它的方法。
过滤器
NestJS中的过滤器(Filter)是一种用于处理HTTP请求和响应的函数,它可以在请求到达控制器之前或之后执行一些操作。过滤器可以用于实现数据转换、错误处理、响应格式化等功能。在NestJS中,过滤器可以是全局的,也可以是局部的。以下是一个过滤器的示例代码:
import { ExceptionFilter, Catch, ArgumentsHost } from '@nestjs/common';
import { Request, Response } from 'express';
@Catch(HttpException)
export class HttpExceptionFilter implements ExceptionFilter {
catch(exception: HttpException, host: ArgumentsHost) {
const ctx = host.switchToHttp();
const response = ctx.getResponse<Response>();
const request = ctx.getRequest<Request>();
const status = exception.getStatus();
response
.status(status)
.json({
statusCode: status,
timestamp: new Date().toISOString(),
path: request.url,
});
}
}
在上面的代码中,我们定义了一个名为HttpExceptionFilter的过滤器类,它实现了ExceptionFilter接口。在catch()方法中,我们获取了请求对象和响应对象,并将异常的状态码和请求的URL添加到响应中。要在应用程序中使用过滤器,我们需要将其添加到模块或控制器中。以下是一个将过滤器添加到模块中的示例代码:
import { Module, NestModule, MiddlewareConsumer } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { HttpExceptionFilter } from './http-exception.filter';
@Module({
imports: [],
controllers: [AppController],
providers: [AppService],
})
export class AppModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
consumer
.apply(LoggerMiddleware)
.forRoutes('*');
}
}
在上面的代码中,我们将HttpExceptionFilter过滤器添加到了模块中,并使用@Catch()装饰器来指定过滤器要捕获的异常类型
小结
以上就是nestjs中涉及到的一些前端不太熟悉的概念,这里以学习的态度进行归纳整理,希望对你有帮助。