当前位置: 首页 > 科技观察

Nest.js使用Express但不完全,那又怎样?

时间:2023-03-19 02:07:20 科技观察

Node.js提供了http模块来监听端口,处理http请求,返回响应,这是它主要做的事情。但是http模块的api太原始了,直接根据它来处理请求和响应比较麻烦,所以我们会用express这样的库封装一层。这一层做的就是在request和response中增加了很多处理request和response的方法,满足各种场景的需要,处理路由。而且,它还提供了一个中间件调用链,方便一些代码的复用。这个中间件调用链称为洋葱模型。但是这一层并没有解决架构问题:模块多了怎么办,怎么管理?Model、View、Controller如何划分?等等。因此,在使用Node.js作为后端服务时,我们会多加一层来解决架构问题。这一层的框架有eggjs(来自蚂蚁)、midwayjs(来自淘宝)、nestjs(来自国外)。nestjs是其中的佼佼者:这一层底层还是express、koa等,只是在那些http框架的基础上解决了架构问题。而且,nestjs有一件事情做得很好。不依赖任何http平台,可以灵活切换。那么nestjs是如何切换底层平台的呢?想想react是怎么把vdom渲染成canvas、dom、native的?定义一个统一的接口,各个平台的渲染逻辑都实现了这些接口。这种模式称为适配器模式。适配器模式是指当使用第三方实现的功能时,不直接依赖它,而是定义一层接口,让第三方适配这一层接口。这样就可以集成任何适配该接口的方案,方案可以灵活切换。Nest.js为底层的http平台提供了一层接口(HttpServer),并定义了一堆使用的方法:因为ts的接口必须实现所有的方法,为了简化,它继承了一层抽象类AbstractHttpAdapter,将需要实现的方法定义为抽象的。那么express或者fastify等其他平台只要继承适配器类并实现抽象方法就可以访问Nest.js:比如ExpressAdapter:或者FastifyAdapter:这些逻辑分别放在platform-express和platform-fastify包里面:Nest.js第一行代码是调用create:在create中会选择一个httpAdapter来创建服务:默认是express:这样后面要调用的request和response的方法都是express。比如在controller中可以使用@Request装饰器注入reqeust对象,可以调用reqeust的各种方法。import{Controller,Get,Request}from'@nestjs/common';@Controller('cats')exportclassCatsController{@Get()findAll(@@Request()request:Request):string{return'这个动作返回所有的猫';如果你想调用接口以外的一些平台特定的方法,Nest.js也支持,那么使用@Req注入:import{Controller,Get,Req}from'@nestjs/common';@Controller('cats')exportclassCatsController{@Get()findAll(@@Req()request:Request):string{return'这个动作返回所有的猫';}}这注入了特定平台如express的原始请求对象,你可以直接使用它的所有方法。另外,如果确实要使用Express平台的特定API,可以在NestFactory.create的时候指定相应的类型参数,这样就可以做相应的类型提示和检查了:但是这个是和特定平台耦合的,除非一定不要切换平台,否则不推荐。http平台就是这么做的。同样,websocket平台也是这样:定义了统一的接口,socketio和websocket分别通过adapter连接到socketio和websocket,可以灵活切换:Nest。Processing:总结Node.js提供了一个http模块来监听端口和处理请求响应,但是它的api太原始了,所以我们会在express层封装一层提供更多有用的请求和响应api但是这一层并没有解决架构问题。引入MVC、IOC等架构,还需要再封装一层,使用Egg.js、Midway.js、Nest.js等更高级别的后端框架,其中Nest.js最为优越。Nest.js针对与底层http平台的集成做了特殊的设计,采用adapter模式为底层平台提供了一层适配接口,可以灵活切换不同的http平台。但它也支持特定于平台的API。比如@Req可以用来在controller中注入底层的request对象,也可以在创建容器的时候传入对应平台的类型参数。Nest.js默认使用Express,但是使用Express也不是完全正确的,因为可以灵活切换。这就是适配器模式的美妙之处。