使用NestJS开发Node.js应用的方法
nestjs 最早在 2017.1 月立项,2017.5 发布第一个正式版本,它是一个基于 express,使用 typescript 开发的后端框架。设计之初,主要用来解决开发 node.js 应用时的架构问题,灵感来源于 angular。在本文中,我将粗略介绍 nestjs 中的一些亮点。
组件容器
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 相似,同是使用依赖注入的设计模式开发
当使用某个对象时,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); }
数据验证
得益于 与对传入参数的验证变的非常简单:
// 创建 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
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
推荐阅读
-
Node.js 使用axios读写influxDB的方法示例
-
使用设计模式中的Singleton单例模式来开发iOS应用程序
-
iOS应用开发中使用设计模式中的观察者模式的实例
-
详解iOS App开发中UIViewController的loadView方法使用
-
Android开发中使用外部应用获取SD卡状态的方法
-
Android开发实现Launcher3应用列表修改透明背景的方法
-
使用JavaScript实现node.js中的path.join方法
-
使用vs2019进行Linux远程开发的方法步骤
-
iOS的UI开发中Modal的使用与主流应用UI结构介绍
-
iOS开发中UITableview控件的基本使用及性能优化方法