使用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圆形浮动菜单特效代码
Mar 03 Javascript
JS日期和时间选择控件升级版(自写)
Aug 02 Javascript
jquery的选择器的使用技巧之如何选择input框
Sep 22 Javascript
微信js-sdk界面操作接口用法示例
Oct 12 Javascript
详解handlebars+require基本使用方法
Dec 21 Javascript
利用NPM淘宝的node.js镜像加速nvm
Mar 27 Javascript
xmlplus组件设计系列之选项卡(Tabbar)(5)
May 03 Javascript
详解Node.js 命令行程序开发教程
Jun 07 Javascript
详解AngularJS之$window窗口对象
Jan 17 Javascript
jQuery 防止相同的事件快速重复触发方法
Feb 08 jQuery
JsChart组件使用详解
Mar 04 Javascript
详解微信小程序之scroll-view的flex布局问题
Jan 16 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应用提速面面观
2006/10/09 PHP
PHP中的类-什么叫类
2006/11/20 PHP
php 深入理解strtotime函数的使用详解
2013/05/23 PHP
php中如何判断一个网页请求是ajax请求还是普通请求
2013/08/10 PHP
Smarty中常用变量操作符汇总
2014/10/27 PHP
PHP设计模式之装饰者模式代码实例
2015/05/11 PHP
php准确获取文件MIME类型的方法
2015/06/17 PHP
CI框架中数据库操作函数$this-&gt;db-&gt;where()相关用法总结
2016/05/17 PHP
PHP实现的简单对称加密与解密方法实例小结
2017/08/28 PHP
php+Ajax无刷新验证用户名操作实例详解
2019/03/04 PHP
laravel框架模板之公共模板、继承、包含实现方法分析
2019/08/30 PHP
php使用yield对性能提升的测试实例分析
2019/09/19 PHP
IE6与IE7中,innerHTML获取param的区别
2009/03/15 Javascript
javascript面向对象之this关键词用法分析
2015/01/13 Javascript
包含中国城市的javascript对象实例
2015/08/03 Javascript
Bootstrap每天必学之栅格系统(布局)
2015/11/25 Javascript
JavaScript学习笔记之ES6数组方法
2016/03/25 Javascript
浅谈$_FILES数组为空的原因
2017/02/16 Javascript
Nodejs中Express 常用中间件 body-parser 实现解析
2017/05/22 NodeJs
jquery实现图片轮播器
2017/05/23 jQuery
BootStrap下的弹出框加载select2框架失败的解决方法
2017/08/31 Javascript
利用JQuery操作iframe父页面、子页面的元素和方法汇总
2017/09/10 jQuery
微信小程序使用wxParse解析html的方法教程
2018/07/06 Javascript
Vue实现日历小插件
2019/06/26 Javascript
解决layer.msg 不居中 ifram中的问题
2019/09/05 Javascript
JavaScript中ES6规范中let和const的用法和区别
2020/08/06 Javascript
python解析xml文件操作实例
2014/10/05 Python
TensorFlow实现RNN循环神经网络
2018/02/28 Python
解决python中无法自动补全代码的问题
2018/12/04 Python
python实现简单多人聊天室
2018/12/11 Python
django框架使用views.py的函数对表进行增删改查内容操作详解【models.py中表的创建、views.py中函数的使用,基于对象的跨表查询】
2019/12/12 Python
Canvas中设置width与height的问题浅析
2018/11/01 HTML / CSS
西班牙香水和化妆品连锁店:Druni
2019/05/05 全球购物
2015年教师节演讲稿范文
2015/03/19 职场文书
单位计划生育责任书
2015/05/09 职场文书
2016年国庆节假期旅游工作总结
2016/04/01 职场文书