使用NestJS開發(fā)Node.js應(yīng)用的方法
NestJS 最早在 2017.1 月立項(xiàng),2017.5 發(fā)布第一個(gè)正式版本,它是一個(gè)基于 Express,使用 TypeScript 開發(fā)的后端框架。設(shè)計(jì)之初,主要用來解決開發(fā) Node.js 應(yīng)用時(shí)的架構(gòu)問題,靈感來源于 Angular。在本文中,我將粗略介紹 NestJS 中的一些亮點(diǎn)。
組件容器
NestJS 采用組件容器的方式,每個(gè)組件與其他組件解耦,當(dāng)一個(gè)組件依賴于另一組件時(shí),需要指定節(jié)點(diǎn)的依賴關(guān)系才能使用:
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 相似,同是使用依賴注入的設(shè)計(jì)模式開發(fā)
當(dāng)使用某個(gè)對(duì)象時(shí),DI 容器已經(jīng)幫你創(chuàng)建,無需手動(dòng)實(shí)例化,來達(dá)到解耦目的:
// 創(chuàng)建一個(gè)服務(wù) @Inject() export class TestService { public find() { return 'hello world'; } } // 創(chuàng)建一個(gè) controller @Controller() export class TestController { controller( private readonly testService: TestService ) {} @Get() public findInfo() { return this.testService.find() } }
為了能讓 TestController
使用 TestService
服務(wù),只需要在創(chuàng)建 module 時(shí),作為 provider 寫入即可:
@Module({ controllers: [TestController], providers: [TestService], }) export class TestModule {}
當(dāng)然,你可以把任意一個(gè)帶 @Inject()
的類,注入到 module 中,供此 module 的 Controller 或者 Service 使用。
背后的實(shí)現(xiàn)基于 Decorator + Reflect Metadata,詳情可以查看深入理解 TypeScript - Reflect Metadata 。
細(xì)?;?Middleware
在使用 Express 時(shí),我們會(huì)使用各種各樣的中間件,譬如日志服務(wù)、超時(shí)攔截,權(quán)限驗(yàn)證等。在 NestJS 中,Middleware 功能被劃分為 Middleware、Filters、Pipes、Grards、Interceptors。
例如使用 Filters,來捕獲處理應(yīng)用中拋出的錯(cuò)誤:
@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 數(shù)據(jù),使得返回?cái)?shù)據(jù)格式是 { 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,當(dāng)不具有 'admin' 角色時(shí),返回 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); }
數(shù)據(jù)驗(yàn)證
得益于class-validator 與class-transformer 對(duì)傳入?yún)?shù)的驗(yàn)證變的非常簡(jiǎn)單:
// 創(chuàng)建 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() } }
當(dāng)所傳入?yún)?shù) text 不是 string 時(shí),會(huì)出現(xiàn) 400 的錯(cuò)誤。
GraphQL
GraphQL 由 facebook 開發(fā),被認(rèn)為是革命性的 API 工具,因?yàn)樗梢宰尶蛻舳嗽谡?qǐng)求中指定希望得到的數(shù)據(jù),而不像傳統(tǒng)的 REST 那樣只能在后端預(yù)定義。
NestJS 對(duì) Apollo server 進(jìn)行了一層包裝,使得能在 NestJS 中更方便使用。
在 Express 中使用 Apollo server 時(shí):
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 實(shí)現(xiàn)微服務(wù)開發(fā)、配合 TypeORM 、以及 Prisma 等特點(diǎn),在這里就不展開了。
參考
深入理解 TypeScript - Reflect Metadata
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- 利用Dockerfile優(yōu)化Nestjs構(gòu)建鏡像大小詳情
- Dapr+NestJs編寫Pub及Sub裝飾器實(shí)戰(zhàn)示例
- Docker?Compose+Nestjs構(gòu)建Dapr?Redis發(fā)布訂閱分布式應(yīng)用
- NestJS+Redis實(shí)現(xiàn)緩存步驟詳解
- nestjs返回給前端數(shù)據(jù)格式的封裝實(shí)現(xiàn)
- NestJs使用Mongoose對(duì)MongoDB操作的方法
- nestjs中異常過濾器Exceptionfilter的具體使用
- NestJs 靜態(tài)目錄配置詳解
- nestjs搭建HTTP與WebSocket服務(wù)詳細(xì)過程
相關(guān)文章
node.js中的console.timeEnd方法使用說明
這篇文章主要介紹了node.js中的console.timeEnd方法使用說明,本文介紹了console.timeEnd的方法說明、語法、使用實(shí)例和實(shí)現(xiàn)源碼,需要的朋友可以參考下2014-12-12Nodejs中調(diào)用系統(tǒng)命令、Shell腳本和Python腳本的方法和實(shí)例
這篇文章主要介紹了Nodejs中調(diào)用系統(tǒng)命令、Shell腳本和Python腳本的方法和實(shí)例,本文給出了利用子進(jìn)程調(diào)用系統(tǒng)命令、執(zhí)行系統(tǒng)命令、調(diào)用傳參數(shù)的shell腳本、調(diào)用python腳本的例子,需要的朋友可以參考下2015-01-01node.js平臺(tái)下的mysql數(shù)據(jù)庫配置及連接
本文主要介紹了node.js平臺(tái)下的mysql數(shù)據(jù)庫配置及連接的相關(guān)知識(shí)。具有很好的參考價(jià)值,下面跟著小編一起來看下吧2017-03-03Node.js基礎(chǔ)入門之緩存區(qū)與文件操作詳解
Node.js是一個(gè)基于Chrome?V8引擎的JavaScript運(yùn)行時(shí)。類似于Java中的JRE,.Net中的CLR。本文將詳細(xì)為大家介紹Node.js中的緩存區(qū)與文件操作,感興趣的可以了解一下2022-03-03