使用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不同页面传值的改进版
Sep 30 Javascript
js实现动态改变字体大小代码
Jan 02 Javascript
jQuery拖拽div实现思路
Feb 19 Javascript
js 实现浏览历史记录示例
Apr 20 Javascript
JS实现浏览器状态栏文字从右向左弹出效果代码
Oct 27 Javascript
js仿小米官网图片轮播特效
Sep 29 Javascript
利用js+css+html实现固定table的列头不动
Dec 08 Javascript
jQuery.parseJSON()函数详解
Feb 28 jQuery
js实现图片粘贴到网页
Dec 06 Javascript
Vue常用的全选/反选的示例代码
Feb 19 Javascript
javascript实现移动端红包雨页面
Jun 23 Javascript
quickjs 封装 JavaScript 沙箱详情
Nov 02 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来改写404错误页让你的页面更友好
2013/01/24 PHP
php设置编码格式的方法
2013/03/05 PHP
浅析is_writable的php实现
2013/06/18 PHP
php ckeditor上传图片文件名乱码解决方法
2013/11/15 PHP
php中opendir函数用法实例
2014/11/15 PHP
Joomla语言翻译类Jtext用法分析
2016/05/05 PHP
PHP中常用的数组操作方法笔记整理
2016/05/16 PHP
PHP实现的用户注册表单验证功能简单示例
2019/02/25 PHP
PHP登录验证功能示例【用户名、密码、验证码、数据库、已登陆验证、自动登录和注销登录等】
2019/02/25 PHP
Lazy Load 延迟加载图片的jQuery插件中文使用文档
2012/10/18 Javascript
jQuery切换网页皮肤并保存到Cookie示例代码
2014/06/16 Javascript
javascript使用for循环批量注册的事件不能正确获取索引值的解决方法
2014/12/20 Javascript
JQuery.get提交页面不跳转的解决方法
2015/01/13 Javascript
JavaScript实现同一页面内两个表单互相传值的方法
2015/08/12 Javascript
js实现五星评价功能
2017/03/08 Javascript
JS异步加载的三种实现方式
2017/03/16 Javascript
vue 怎么创建组件及组件使用方法
2017/07/27 Javascript
详解组件库的webpack构建速度优化
2018/06/18 Javascript
Vue $emit $refs子父组件间方法的调用实例
2018/09/12 Javascript
生产制造追溯系统之再说条码打印
2019/06/03 Javascript
Python中zip()函数用法实例教程
2014/07/31 Python
Python标准库之循环器(itertools)介绍
2014/11/25 Python
Python AES加密模块用法分析
2017/05/22 Python
python实现逆序输出一个数字的示例讲解
2018/06/25 Python
Random 在 Python 中的使用方法
2018/08/09 Python
Python3.8中使用f-strings调试
2019/05/22 Python
python爬取2021猫眼票房字体加密实例
2021/02/19 Python
法国在线宠物店:zooplus.fr
2018/02/23 全球购物
生态学毕业生自荐信
2013/10/27 职场文书
办公室岗位职责
2014/02/12 职场文书
会计电算化专业自荐信
2014/03/15 职场文书
安全协议书
2014/04/23 职场文书
高中信息技术教学反思
2016/02/16 职场文书
2016年第二十届“母亲节暨幸福工程救助贫困母亲活动日”活动总结
2016/04/06 职场文书
HTML中table表格拆分合并(colspan、rowspan)
2021/04/07 HTML / CSS
用Python提取PDF表格的方法
2021/04/11 Python