使用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 相关文章推荐
Javascript(AJAX)解析XML的代码(兼容FIREFOX/IE)
Jul 11 Javascript
jQuery中outerHeight()方法用法实例
Jan 19 Javascript
JavaScript的内存释放问题详解
Jan 21 Javascript
jquery.cookie实现的客户端购物车操作实例
Dec 24 Javascript
Javascript类型系统之String字符串类型详解
Jun 21 Javascript
bootstrapValidator表单验证插件学习
Dec 30 Javascript
详解Node.js实现301、302重定向服务
Apr 07 Javascript
JavaScript函数表达式详解及实例
May 05 Javascript
详解如何在webpack中做预渲染降低首屏空白时间
Aug 22 Javascript
VuePress 快速踩坑小结
Feb 14 Javascript
node 标准输入流和输出流代码实例
Sep 19 Javascript
浅谈Vue为什么不能检测数组变动
Oct 14 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
为查询结果建立向后/向前按钮
2006/10/09 PHP
Smarty+QUICKFORM小小演示
2007/02/25 PHP
php 在线打包_支持子目录
2008/06/28 PHP
Could not load type System.ServiceModel.Activation.HttpModule解决办法
2012/12/29 PHP
PHP实现带重试功能的curl连接示例
2016/07/28 PHP
PHP 配置后台登录以及模板引入
2017/01/24 PHP
PHP实现图片压缩
2020/09/09 PHP
Jquery下attr和removeAttr的使用方法
2010/12/28 Javascript
使用jQuery快速解决input中placeholder值在ie中无法支持的问题
2014/01/02 Javascript
js转化毫秒为时间格式代码
2014/04/10 Javascript
jQuery中prop()方法用法实例
2015/01/05 Javascript
基于JavaScript实现高德地图和百度地图提取行政区边界经纬度坐标
2016/01/22 Javascript
js数组常用操作方法小结(增加,删除,合并,分割等)
2016/08/02 Javascript
BootStrap Validator 版本差异问题导致的submitHandler失效问题的解决方法
2016/12/01 Javascript
JavaScript易错知识点整理
2016/12/05 Javascript
JS闭包与延迟求值用法示例
2016/12/22 Javascript
JavaScript验证知识整理
2017/03/24 Javascript
微信小程序商城项目之侧栏分类效果(1)
2017/04/17 Javascript
JS实现经典的中国地区三级联动下拉菜单功能实例【测试可用】
2017/06/06 Javascript
详谈for循环里面的break和continue语句
2017/07/20 Javascript
vue 权限认证token的实现方法
2018/07/17 Javascript
前后端如何实现登录token拦截校验详解
2018/09/03 Javascript
基于Fixed定位的框选功能的实现代码
2019/05/13 Javascript
Fabric 应用案例
2016/08/28 Python
使用requests库制作Python爬虫
2018/03/25 Python
pandas ix &amp;iloc &amp;loc的区别
2019/01/10 Python
Django中使用Whoosh进行全文检索的方法
2019/03/31 Python
python 求1-100之间的奇数或者偶数之和的实例
2019/06/11 Python
python爬虫爬取监控教务系统的思路详解
2020/01/08 Python
8款使用 CSS3 实现超炫的 Loading(加载)的动画效果
2015/03/17 HTML / CSS
德国高品质男装及配饰商城:Cultizm(Raw Denim原色牛仔裤)
2018/04/16 全球购物
Harrods美国:英国最大的百货公司
2018/11/04 全球购物
阿玛尼美妆英国官网:Giorgio Armani Beauty英国
2019/03/28 全球购物
澳大利亚著名的纺织品品牌:Canningvale
2020/05/05 全球购物
优秀生推荐信范文
2013/11/28 职场文书
故意伤害辩护词
2015/05/21 职场文书