使用NestJS开发Node.js应用的方法


Posted in Javascript onDecember 03, 2018

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-validator 与class-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 等特点,在这里就不展开了。

参考

深入理解 TypeScript - Reflect Metadata

Egg VS NestJS

NestJS 官网

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
最近项目写了一些js,水平有待提高
Jan 31 Javascript
javascrip客户端验证文件大小及文件类型并重置上传
Jan 12 Javascript
JavaScript中的排序算法代码
Feb 22 Javascript
extjs tabpanel限制选项卡数量实现思路及代码
Apr 02 Javascript
JS关闭窗口与JS关闭页面的几种方法小结
Dec 17 Javascript
js 3秒后跳转页面的实现代码
Mar 10 Javascript
js实现获取两个日期之间所有日期的方法
Jun 17 Javascript
微信小程序 Page()函数详解
Oct 17 Javascript
快速掌握jQuery插件WebUploader文件上传
Nov 07 Javascript
从零学习node.js之mysql数据库的操作(五)
Feb 24 Javascript
解决angular2 获取到的数据无法实时更新的问题
Aug 31 Javascript
js实现登录拖拽窗口
Feb 10 Javascript
写gulp遇到的ES6问题详解
Dec 03 #Javascript
使用mpvue搭建一个初始小程序及项目配置方法
Dec 03 #Javascript
JS基于Location实现访问Url、重定向及刷新页面的方法分析
Dec 03 #Javascript
koa2实现登录注册功能的示例代码
Dec 03 #Javascript
react-router 路由切换动画的实现示例
Dec 03 #Javascript
Vue.js 中的 v-model 指令及绑定表单元素的方法
Dec 03 #Javascript
ng-zorro-antd 入门初体验
Dec 03 #Javascript
You might like
php实现快速排序法函数代码
2012/08/27 PHP
深入理解PHP中的Session和Cookie
2013/06/21 PHP
javascript CSS画图之基础篇
2009/07/29 Javascript
js、jquery图片动画、动态切换示例代码
2014/06/03 Javascript
node.js中的events.emitter.once方法使用说明
2014/12/10 Javascript
javascript实现根据时间段显示问候语的方法
2015/06/18 Javascript
Jquery EasyUI实现treegrid上显示checkbox并取选定值的方法
2016/04/29 Javascript
Javascript实现前端简单的路由实例
2016/09/11 Javascript
禁用backspace网页回退功能的实现代码
2016/11/15 Javascript
Javascript 高性能之递归,迭代,查表法详解及实例
2017/01/08 Javascript
数组Array的排序sort方法
2017/02/17 Javascript
Linux使用Node.js建立访问静态网页的服务实例详解
2017/03/21 Javascript
easyui关于validatebox实现多重规则验证的方法(必看)
2017/04/12 Javascript
JS封装的模仿qq右下角消息弹窗功能示例
2018/08/22 Javascript
vue图片上传本地预览组件使用详解
2019/02/20 Javascript
vue实现搜索功能
2019/05/28 Javascript
使用layui实现树形结构的方法
2019/09/20 Javascript
微信小程序实现时间戳格式转换
2020/07/20 Javascript
详解Vue的七种传值方式
2021/02/08 Vue.js
python共享引用(多个变量引用)示例代码
2013/12/04 Python
python利用matplotlib库绘制饼图的方法示例
2016/12/18 Python
python format 格式化输出方法
2018/07/16 Python
Python3.6中Twisted模块安装的问题与解决
2019/04/15 Python
python3.7 sys模块的具体使用
2019/07/22 Python
日常奢侈品,轻松购物:Verishop
2019/08/20 全球购物
人力资源管理专业应届生求职信
2013/09/28 职场文书
2014年学校后勤工作总结
2014/12/06 职场文书
抗洪救灾感谢信
2015/01/22 职场文书
员工离职感谢信
2015/01/22 职场文书
党员廉洁自律个人总结
2015/02/13 职场文书
2015年实习单位评语
2015/03/25 职场文书
幼儿园教师工作总结2015
2015/04/02 职场文书
2015年车间管理工作总结
2015/07/23 职场文书
原生JS中应该禁止出现的写法
2021/05/05 Javascript
python spilt()分隔字符串的实现示例
2021/05/21 Python
Mysql的Table doesn't exist问题及解决
2022/12/24 MySQL