6扑馁、Nest.js 中的管道與驗證器

什么是管道(pipe)?

管道就是一個實現(xiàn)了 PipeTransform 接口并用 @Injectable() 裝飾器修飾的類凉驻。
管道的作用簡單來說就是腻要,可以將輸入的數(shù)據(jù)處理過后輸出。

我們在前面的例子中將參數(shù)驗證的邏輯寫在了控制器中涝登,這就打破了單一責任原則雄家,控制器只應該處理請求的分發(fā),驗證的邏輯應該讓驗證器來做胀滚。
在 Nest 中正確的做法是趟济,使用管道驗證器乱投,改寫我們的 findOne 如下:

    @Get(':id')
    async findOne(@Param('id', new ParseIntPipe()) id): Promise<User> {
        return await this.usersService.findOne(id);
    }

我們使用了 @nestjs/common 包中內(nèi)置的一個管道 ParseIntPipe,它將一個字符串類型的數(shù)據(jù)轉換成一個 int 類型顷编,如果失敗則拋出異常戚炫,現(xiàn)在訪問 http://127.0.0.1:3000/users/exception

{
    "statusCode":400,
    "date":"2018-7-31",
    "path":"/users/exception"
}

我們自定義的錯誤碼又沒了!這可不是我們想要的結果媳纬,看來還是需要自己定義管道驗證器嘹悼。
現(xiàn)在新建一個管道:

$ nest g pi users/pipes/user-id

CREATE /src/users/pipes/user-id/user-id.pipe.ts (216 bytes)

去掉 user-id/ 這一層目錄,默認生成的管道使用的還是老版本的 @Pipe 裝飾器层宫, Nest 5.0 已經(jīng)修改為 @Injectable 裝飾器了,所以我們修改生成的代碼再給它加上兩行打印語句其监,如下:

import { ArgumentMetadata, PipeTransform, Injectable } from '@nestjs/common';

@Injectable()
export class UserIdPipe implements PipeTransform {
  async transform(value: any, metadata: ArgumentMetadata) {
    console.log(value);
    console.log(metadata);
    return value;
  }
}

PipeTransfrom 接口就只有一個 transfrom 方法萌腿, 其中的 value 參數(shù)就是我們需要處理的數(shù)據(jù)源,而 ArgumentMetadata 就是這個對象的一些 元數(shù)據(jù)(metadate)抖苦,它的接口定義是下面這樣的:

export interface ArgumentMetadata {
    type: 'body' | 'query' | 'param' | 'custom';
    metatype?: new (...args) => any;
    data?: string;
}

這里直接引用官方文檔的說明:


image.png

TypeScript接口在編譯期間消失毁菱,所以如果你使用接口而不是類,那么元類型的值將是一個 Object锌历。

現(xiàn)在讓我們的管道工作起來贮庞,修改 findOne 如下:

    @Get(':id')
    async findOne(@Param('id', new UserIdPipe()) id): Promise<User> {

        return await this.usersService.findOne(id);
    }

訪問 http://127.0.0.1:3000/users/exception, 看到控制臺輸出:

exception
{ metatype: [Function: Object], type: 'param', data: 'id' }

我們已經(jīng)在管道中拿到了參數(shù)的值和元數(shù)據(jù)究西,我們可以寫自己的驗證邏輯然后在驗證失敗的時候讓他拋出 ApiException:

import { ArgumentMetadata, PipeTransform, Injectable, HttpStatus } from '@nestjs/common';
import { ApiException } from 'common/exceptions/api.exception';
import { ApiErrorCode } from 'common/enums/api-error-code.enum';

@Injectable()
export class UserIdPipe implements PipeTransform {
  async transform(value: any, metadata: ArgumentMetadata) {
   
    value = parseInt(value)

    if(isNaN(value) || typeof value !== 'number' || value <= 0) {
      throw new ApiException('用戶ID無效', ApiErrorCode.USER_ID_INVALID, HttpStatus.BAD_REQUEST);
    }

    return value;
  }
}

訪問 http://127.0.0.1:3000/users/exception窗慎,發(fā)現(xiàn)我們的管道工作的很好,我們自定義的業(yè)務狀態(tài)碼也回來了啦:

{
    "errorCode":10001,
    "errorMessage":"用戶ID無效",
    "date":"2018-8-1",
    "path":"/users/exception"
}

本篇只介紹管道最基本的用法卤材,在后面我們會循序漸進的學習管道的高級用法遮斥。

上一篇:5、Nest.js 中的異常處理和AOP編程
下一篇:7扇丛、Nest.js 中的類驗證器

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末术吗,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子帆精,更是在濱河造成了極大的恐慌较屿,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,639評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件卓练,死亡現(xiàn)場離奇詭異隘蝎,居然都是意外死亡,警方通過查閱死者的電腦和手機昆庇,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,277評論 3 385
  • 文/潘曉璐 我一進店門末贾,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人整吆,你說我怎么就攤上這事拱撵』源ǎ” “怎么了?”我有些...
    開封第一講書人閱讀 157,221評論 0 348
  • 文/不壞的土叔 我叫張陵拴测,是天一觀的道長乓旗。 經(jīng)常有香客問我,道長集索,這世上最難降的妖魔是什么屿愚? 我笑而不...
    開封第一講書人閱讀 56,474評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮务荆,結果婚禮上妆距,老公的妹妹穿的比我還像新娘。我一直安慰自己函匕,他們只是感情好娱据,可當我...
    茶點故事閱讀 65,570評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著盅惜,像睡著了一般中剩。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上抒寂,一...
    開封第一講書人閱讀 49,816評論 1 290
  • 那天结啼,我揣著相機與錄音,去河邊找鬼屈芜。 笑死郊愧,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的沸伏。 我是一名探鬼主播糕珊,決...
    沈念sama閱讀 38,957評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼毅糟!你這毒婦竟也來了红选?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 37,718評論 0 266
  • 序言:老撾萬榮一對情侶失蹤姆另,失蹤者是張志新(化名)和其女友劉穎喇肋,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體迹辐,經(jīng)...
    沈念sama閱讀 44,176評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡蝶防,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,511評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了明吩。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片间学。...
    茶點故事閱讀 38,646評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出低葫,到底是詐尸還是另有隱情详羡,我是刑警寧澤,帶...
    沈念sama閱讀 34,322評論 4 330
  • 正文 年R本政府宣布嘿悬,位于F島的核電站实柠,受9級特大地震影響,放射性物質發(fā)生泄漏善涨。R本人自食惡果不足惜窒盐,卻給世界環(huán)境...
    茶點故事閱讀 39,934評論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望钢拧。 院中可真熱鬧蟹漓,春花似錦、人聲如沸源内。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,755評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽姿锭。三九已至,卻和暖如春伯铣,著一層夾襖步出監(jiān)牢的瞬間呻此,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,987評論 1 266
  • 我被黑心中介騙來泰國打工腔寡, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留焚鲜,地道東北人。 一個月前我還...
    沈念sama閱讀 46,358評論 2 360
  • 正文 我出身青樓放前,卻偏偏與公主長得像忿磅,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子凭语,可洞房花燭夜當晚...
    茶點故事閱讀 43,514評論 2 348

推薦閱讀更多精彩內(nèi)容