使用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 相关文章推荐
Lazy Load 延迟加载图片的jQuery插件中文使用文档
Oct 18 Javascript
js点击更换背景颜色或图片的实例代码
Jun 25 Javascript
JS中判断null、undefined与NaN的方法
Mar 26 Javascript
js中window.open打开一个新的页面
Aug 10 Javascript
理解jquery事件冒泡
Jan 03 Javascript
seajs模块之间依赖的加载以及模块的执行
Oct 21 Javascript
关闭Vue计算属性自带的缓存功能方法
Mar 02 Javascript
详解使用Next.js构建服务端渲染应用
Jul 10 Javascript
angularJs中ng-model-options设置数据同步的方法
Sep 30 Javascript
JS中的防抖与节流及作用详解
Apr 01 Javascript
在vue中使用vant TreeSelect分类选择组件操作
Nov 02 Javascript
JavaScript构造函数原理及实现流程解析
Nov 19 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 Session_Regenerate_ID函数双释放内存破坏漏洞
2011/01/27 PHP
Apache中php.ini的设置方法
2013/02/28 PHP
推荐几款用 Sublime Text 开发 Laravel 所用到的插件
2014/10/30 PHP
php生成rss类用法实例
2015/04/14 PHP
php版微信开发之接收消息,自动判断及回复相应消息的方法
2016/09/23 PHP
js获取div高度的代码
2008/08/09 Javascript
js 判断浏览器类型 去全角、半角空格 自动关闭当前窗口
2009/04/10 Javascript
document.getElementById的简写方式(获取id对象的简略写法)
2010/09/10 Javascript
jquery移除button的inline onclick事件(已测试及兼容浏览器)
2013/01/25 Javascript
hover的用法及live的用法介绍(鼠标悬停效果)
2013/03/29 Javascript
javascript实现点击后变换按钮显示文字的方法
2015/05/13 Javascript
限制只能输入数字的实现代码
2016/05/16 Javascript
正则表达式基本语法及表单验证操作详解【基于JS】
2017/04/07 Javascript
详解nodejs实现本地上传图片并预览功能(express4.0+)
2017/06/28 NodeJs
vue中实现先请求数据再渲染dom分享
2018/03/17 Javascript
浅谈发布订阅模式与观察者模式
2019/04/09 Javascript
jQuery实现鼠标滑动切换图片
2020/05/27 jQuery
echarts实现获取datazoom的起始值(包括x轴和y轴)
2020/07/20 Javascript
python命令行参数sys.argv使用示例
2014/01/28 Python
python创建临时文件夹的方法
2015/07/06 Python
Python实现简单网页图片抓取完整代码实例
2017/12/15 Python
python爬虫爬取网页表格数据
2018/03/07 Python
python如何实现从视频中提取每秒图片
2020/10/22 Python
解决python replace函数替换无效问题
2020/01/18 Python
Django实现将views.py中的数据传递到前端html页面,并展示
2020/03/16 Python
python爬虫把url链接编码成gbk2312格式过程解析
2020/06/08 Python
基于Python爬取股票数据过程详解
2020/10/21 Python
Anaconda的安装与虚拟环境建立
2020/11/18 Python
在浏览器端如何得到服务器端响应的XML数据
2012/11/24 面试题
导游的职业规划书范文
2013/12/27 职场文书
中餐厅主管的职责范文
2014/02/04 职场文书
解除劳动合同协议书(样本)
2014/10/02 职场文书
刑事附带民事诉讼答辩状
2015/05/22 职场文书
Java虚拟机内存结构及编码实战分享
2022/04/07 Java/Android
Docker 镜像介绍以及commit相关操作
2022/04/13 Servers