使用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获取元素偏移量的方法有哪些
Jun 24 Javascript
基于jquery的手风琴图片展示效果实现方法
Dec 16 Javascript
jQuery实现的Tab滑动选项卡及图片切换(多种效果)小结
Sep 14 Javascript
jQuery实现鼠标滑过链接控制图片的滑动展开与隐藏效果
Oct 28 Javascript
javascript针对cookie的基本操作实例详解
Nov 30 Javascript
jQuery代码实现对话框右上角菜单带关闭×
May 03 Javascript
用JS实现图片轮播效果代码(一)
Jun 26 Javascript
Angular4项目中添加i18n国际化插件ngx-translate的步骤详解
Jul 02 Javascript
javascript 面向对象实战思想分享
Sep 07 Javascript
详解vue-meta如何让你更优雅的管理头部标签
Jan 18 Javascript
layui按条件隐藏表格列的实例
Sep 19 Javascript
vue实现计步器功能
Nov 01 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
常用星际术语索引(新手指南)
2020/03/04 星际争霸
php在线代理转向代码
2012/05/05 PHP
PHP 解决session死锁的方法
2013/06/20 PHP
php中{}大括号是什么意思
2013/12/01 PHP
PHP5.5和之前的版本empty函数的不同之处
2014/06/13 PHP
PHP网页游戏学习之Xnova(ogame)源码解读(十二)
2014/06/25 PHP
基于php实现的php代码加密解密类完整实例
2016/10/12 PHP
利用PHP实现开心消消乐的算法示例
2017/10/12 PHP
PHP中遍历数组的三种常用方法实例分析
2019/06/24 PHP
javascript面向对象之二 命名空间
2011/02/08 Javascript
Javascript创建自定义对象 创建Object实例添加属性和方法
2012/06/04 Javascript
时间戳转换为时间 年月日时间的JS函数
2013/08/19 Javascript
jquery ajax传递中文参数乱码问题及解决方法说明
2014/02/07 Javascript
jquery对象和javascript对象即DOM对象相互转换
2014/08/07 Javascript
jQuery 插件开发指南
2014/11/14 Javascript
JavaScript中的object转换成number或string规则介绍
2014/12/31 Javascript
jQuery的ajax下载blob文件
2016/07/21 Javascript
JS设计模式之策略模式概念与用法分析
2018/02/05 Javascript
vue element-ui table表格滚动加载方法
2018/03/02 Javascript
详解如何在Node.js的httpServer中接收前端发送的arraybuffer数据
2018/11/11 Javascript
这15个Vue指令,让你的项目开发爽到爆
2019/10/11 Javascript
Nodejs文件上传、监听上传进度的代码
2020/03/27 NodeJs
结合axios对项目中的api请求进行封装操作
2020/09/21 Javascript
[48:21]林俊杰圣堂刺客超神杀戮秀
2014/10/29 DOTA
Python中的pygal安装和绘制直方图代码分享
2017/12/08 Python
Python WEB应用部署的实现方法
2019/01/02 Python
python中pip的使用和修改下载源的方法
2019/07/08 Python
关于pymysql模块的使用以及代码详解
2019/09/01 Python
python性能测量工具cProfile使用解析
2019/09/26 Python
Python绘制K线图之可视化神器pyecharts的使用
2021/03/02 Python
CSS3动画和HTML5新特性详解
2020/08/31 HTML / CSS
来自世界各地的优质葡萄酒:VineShop24
2018/07/09 全球购物
中东奢侈品市场:Coveti
2019/05/12 全球购物
北京离婚协议书范文2014
2014/09/29 职场文书
个人学习群众路线心得体会
2014/11/05 职场文书
Django + Taro 前后端分离项目实现企业微信登录功能
2022/04/07 Python