使用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 相关文章推荐
十个迅速提升JQuery性能让你的JQuery跑得更快
Dec 10 Javascript
jquery()函数的三种语法介绍
Oct 09 Javascript
浅谈javascript中的DOM方法
Jul 16 Javascript
js命名空间写法示例
Dec 18 Javascript
你不知道的高性能JAVASCRIPT
Jan 18 Javascript
jquery实现超简单的瀑布流布局【推荐】
Mar 08 Javascript
微信小程序列表渲染功能之列表下拉刷新及上拉加载的实现方法分析
Nov 27 Javascript
原生JS实现动态加载js文件并在加载成功后执行回调函数的方法
Dec 30 Javascript
20道JS原理题助你面试一臂之力(必看)
Jul 22 Javascript
Angular如何由模板生成DOM树的方法
Dec 23 Javascript
微信小程序实现简单的select下拉框
Nov 23 Javascript
前端JS获取URL参数的4种方法总结
Apr 05 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与MySQL交互使用详解
2006/10/09 PHP
PHP中call_user_func_array()函数的用法演示
2012/02/05 PHP
PHP 读取大文件的X行到Y行内容的实现代码
2013/06/24 PHP
深入解析PHP中foreach语句控制数组循环的用法
2015/11/30 PHP
php面向对象之反射功能与用法分析
2017/03/29 PHP
php输出控制函数和输出函数生成静态页面
2019/06/27 PHP
轻轻松松学JS调试(不下载任何工具)
2010/04/14 Javascript
javascript suggest效果 自动完成实现代码分享
2012/02/17 Javascript
网站如何做到完全不需要jQuery也可以满足简单需求
2013/06/27 Javascript
js实现登陆遮罩效果的方法
2015/07/28 Javascript
js判断空对象的实例(超简单)
2016/07/26 Javascript
javascript中的深复制详解及实例分析
2016/12/29 Javascript
微信小程序 slider的简单实例
2017/04/19 Javascript
js动态添加表格逐行添加、删除、遍历取值的实例代码
2018/01/25 Javascript
vue + axios get下载文件功能
2019/09/25 Javascript
vue $set 给数据赋值的实例
2019/11/09 Javascript
node 版本切换的实现
2020/02/02 Javascript
[01:28:44]DOTA2-DPC中国联赛定级赛 RNG vs iG BO3第一场 1月10日
2021/03/11 DOTA
Python2.6版本中实现字典推导 PEP 274(Dict Comprehensions)
2015/04/28 Python
Python中遍历字典过程中更改元素导致异常的解决方法
2016/05/12 Python
python 3.7.0 下pillow安装方法
2018/08/27 Python
对python制作自己的数据集实例讲解
2018/12/12 Python
python f-string式格式化听语音流程讲解
2019/06/18 Python
Python占用的内存优化教程
2019/07/28 Python
python循环输出三角形图案的例子
2019/11/22 Python
django中嵌套的try-except实例
2020/05/21 Python
html5与css3小应用
2013/04/03 HTML / CSS
德国玩具商店:Planet Happy DE
2021/01/16 全球购物
基于Python 函数和方法的区别说明
2021/03/24 Python
市场安全管理制度
2014/01/26 职场文书
初一体育教学反思
2014/01/29 职场文书
餐厅经理岗位职责和岗位目标
2014/02/13 职场文书
2014社区三八妇女节活动总结
2014/03/01 职场文书
辞职书格式样本
2015/02/26 职场文书
如何做好工作总结!
2019/04/10 职场文书
Apache Hudi 加速传统的批处理模式
2022/04/24 Servers