使用 NestJS 开发 Node.js 应用

栏目: Node.js · 发布时间: 5年前

内容简介:NestJS 采用组件容器的方式,每个组件与其他组件解耦,当一个组件依赖于另一组件时,需要指定节点的依赖关系才能使用:与 Angular 相似,同是使用依赖注入的设计模式开发

NestJS 最早在 2017.1 月立项,2017.5 发布第一个正式版本,它是一个基于 Express,使用 TypeScript 开发的后端框架。设计之初,主要用来解决开发 Node.js 应用时的架构问题,灵感来源于 Angular。在本文中,我将粗略介绍 NestJS 中的一些亮点。

组件容器

使用 NestJS 开发 Node.js 应用

NestJS 采用组件容器的方式,每个组件与其他组件解耦,当一个组件依赖于另一组件时,需要指定节点的依赖关系才能使用:

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

@Module({
  imports: [OtherModule],
  controllers: [CatsController],
  providers: [CatsService],
})
export class CatsModule {}
复制代码

依赖注入(DI)

与 Angular 相似,同是使用依赖注入的 设计模式 开发

使用 NestJS 开发 Node.js 应用

当使用某个对象时,DI 容器已经帮你创建,无需手动实例化,来达到解耦目的:

// 创建一个服务
@Inject()
export class TestService {
  public find() {
    return 'hello world';
  }
}

// 创建一个 controller
@Controller()
export class TestController {
  controller(
    private readonly testService: TestService
  ) {}
  
  @Get()
  public findInfo() {
    return this.testService.find()
  }
}
复制代码

为了能让 TestController 使用 TestService 服务,只需要在创建 module 时,作为 provider 写入即可:

@Module({
  controllers: [TestController],
  providers: [TestService],
})
export class TestModule {}
复制代码

当然,你可以把任意一个带 @Inject() 的类,注入到 module 中,供此 module 的 Controller 或者 Service 使用。

背后的实现基于 Decorator + Reflect Metadata,详情可以查看 深入理解 TypeScript - Reflect Metadata

细粒化的 Middleware

在使用 Express 时,我们会使用各种各样的中间件,譬如日志服务、超时拦截,权限验证等。在 NestJS 中,Middleware 功能被划分为 Middleware、Filters、Pipes、Grards、Interceptors。

例如使用 Filters,来捕获处理应用中抛出的错误:

@Catch()
export class AllExceptionsFilter implements ExceptionFilter {
  catch(exception: any, host: ArgumentsHost) {
    const ctx = host.switchToHttp();
    const response = ctx.getResponse();
    const request = ctx.getRequest();
    const status = exception.getStatus();

    // 一些其他做的事情,如使用日志

    response
      .status(status)
      .json({
        statusCode: status,
        timestamp: new Date().toISOString(),
        path: request.url,
      });
  }
}
复制代码

使用 interceptor,拦截 response 数据,使得返回数据格式是 { data: T } 的形式:

import { Injectable, NestInterceptor, ExecutionContext } from '@nestjs/common';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';

export interface Response<T> {
  data: T;
}

@Injectable()
export class TransformInterceptor<T>
  implements NestInterceptor<T, Response<T>> {
  intercept(
    context: ExecutionContext,
    call$: Observable<T>,
  ): Observable<Response<T>> {
    return call$.pipe(map(data => ({ data })));
  }
}
复制代码

使用 Guards,当不具有 'admin' 角色时,返回 401:

import { ReflectMetadata } from '@nestjs/common';
export const Roles = (...roles: string[]) => ReflectMetadata('roles', roles);

@Post()
@Roles('admin')
async create(@Body() createCatDto: CreateCatDto) {
  this.catsService.create(createCatDto);
}
复制代码

数据验证

得益于 class-validatorclass-transformer 对传入参数的验证变的非常简单:

// 创建 Dto
export class ContentDto {
  @IsString()
  text: string
}

@Controller()
export class TestController {
  controller(
    private readonly testService: TestService
  ) {}
  
  @Get()
  public findInfo(
    @Param() param: ContentDto     // 使用
  ) {
    return this.testService.find()
  }
}
复制代码

当所传入参数 text 不是 string 时,会出现 400 的错误。

GraphQL

GraphQL 由 facebook 开发,被认为是革命性的 API 工具,因为它可以让客户端在请求中指定希望得到的数据,而不像传统的 REST 那样只能在后端预定义。

NestJS 对 Apollo server 进行了一层包装,使得能在 NestJS 中更方便使用。

在 Express 中使用 Apollo server 时:

const express = require('express');
const { ApolloServer, gql } = require('apollo-server-express');

// Construct a schema, using GraphQL schema language
const typeDefs = gql`
  type Query {
    hello: String
  }
`;

// Provide resolver functions for your schema fields
const resolvers = {
  Query: {
    hello: () => 'Hello world!',
  },
};

const server = new ApolloServer({ typeDefs, resolvers });

const app = express();
server.applyMiddleware({ app });

const port = 4000;

app.listen({ port }, () =>
  console.log(`Server ready at http://localhost:${port}${server.graphqlPath}`),
);
复制代码

在 NestJS 中使用它:

// test.graphql
type Query {
  hello: string;
}


// test.resolver.ts
@Resolver()
export class {
  @Query()
  public hello() {
    return 'Hello wolrd';
  }
}
复制代码

使用 Decorator 的方式,看起来也更 TypeScript

其他

除上述一些列举外,NestJS 实现微服务开发、配合 TypeORM 、以及 Prisma 等特点,在这里就不展开了。

参考


以上所述就是小编给大家介绍的《使用 NestJS 开发 Node.js 应用》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

信号与噪声

信号与噪声

[美] 纳特•西尔弗 / 胡晓姣、张新、朱辰辰 / 中信出版社 / 2013-8 / 69.00元

【编辑推荐】 从海量的大数据中筛选出真正的信号, “黑天鹅”事件也可提前预知! “本书将成为未来十年内最重要的书籍之一。”——《纽约时报》 “对于每一个关心下一刻可能会发生什么的人来说,这都是本必读书。”——理查德•泰勒 《华尔街日报》2012年度10本最佳非虚构类图书之一 《经济学人》杂志2012年度书籍 亚马逊网站2012年度10本最佳非虚构类图书之一......一起来看看 《信号与噪声》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具