使用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采用数组实现tab菜单切换效果
Dec 12 Javascript
JavaScript如何从listbox里同时删除多个项目
Oct 12 Javascript
JavaScript中合并数组的N种方法
Sep 16 Javascript
Javascript设计模式之观察者模式的多个实现版本实例
Mar 03 Javascript
jquery实现点击变换导航样式的方法
Aug 31 Javascript
Bootstrap菜单按钮及导航实例解析
Sep 09 Javascript
vue2.0开发入门笔记之.vue文件的生成和使用
Sep 19 Javascript
angular4 JavaScript内存溢出问题
Mar 06 Javascript
Javascript获取某个月的天数
May 30 Javascript
JS插件clipboard.js实现一键复制粘贴功能
Dec 04 Javascript
vue过滤器实现日期格式化的案例分析
Jul 02 Javascript
利用PHP实现递归删除链表元素的方法示例
Oct 23 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
解决cPanel无法安装php5.2.17
2014/06/22 PHP
Win10 下安装配置IIS + MySQL + nginx + php7.1.7
2017/08/04 PHP
jquery CSS选择器笔记
2010/03/29 Javascript
js实现点击左右按钮轮播图片效果实例
2015/01/29 Javascript
基于canvas实现的绚丽圆圈效果完整实例
2016/01/26 Javascript
Angular.js中$apply()和$digest()的深入理解
2016/10/13 Javascript
jQuery居中元素scrollleft计算方法示例
2017/01/16 Javascript
Vue分页组件实例代码
2017/04/17 Javascript
ES6学习教程之对象字面量详解
2017/10/09 Javascript
微信小程序利用canvas 绘制幸运大转盘功能
2018/07/06 Javascript
React SSR样式及SEO的实践
2018/10/22 Javascript
js实现简易拖拽的示例
2020/10/26 Javascript
Vue实现菜单切换功能
2020/11/08 Javascript
[00:35]DOTA2上海特级锦标赛 VP战队宣传片
2016/03/04 DOTA
Python日志模块logging简介
2015/04/13 Python
实现python版本的按任意键继续/退出
2016/09/26 Python
浅谈Python中的可迭代对象、迭代器、For循环工作机制、生成器
2019/03/11 Python
python删除文件夹下相同文件和无法打开的图片
2019/07/16 Python
Python学习笔记之Django创建第一个数据库模型的方法
2019/08/07 Python
Django restframework 框架认证、权限、限流用法示例
2019/12/21 Python
Django执行源生mysql语句实现过程解析
2020/11/12 Python
详解通过HTML5 Canvas实现图片的平移及旋转变化的方法
2016/03/22 HTML / CSS
玩具反斗城西班牙网上商城:ToysRUs西班牙
2017/01/19 全球购物
String s = new String(“xyz”);创建了几个String Object?
2015/08/05 面试题
心理学专业毕业生推荐信范文
2013/11/21 职场文书
幼儿园教师奖惩制度
2014/02/01 职场文书
索桥的故事教学反思
2014/02/06 职场文书
太太口服液广告词
2014/03/20 职场文书
中学生学雷锋演讲稿
2014/04/26 职场文书
小学校长竞聘演讲稿
2014/05/16 职场文书
禁毒宣传活动总结
2014/08/26 职场文书
高中生第一学年自我鉴定
2014/09/12 职场文书
教师党员批评与自我批评
2014/10/15 职场文书
2015年城乡环境综合治理工作总结
2015/07/24 职场文书
nginx 反向代理之 proxy_pass的实现
2021/03/31 Servers
css3实现背景图片颜色修改的多种方式
2021/04/13 HTML / CSS