Трубы
Канал - гэта клас, анатаваны дэкаратарам @Injectable()
, які рэалізуе інтэрфейс PipeTransform
.
Трубы маюць два тыповых выпадку выкарыстання:
- пераўтварэнне : пераўтварэнне ўваходных дадзеных у жаданую форму (напрыклад, з радка ў цэлы лік)
- праверка : ацэнка ўваходных даных і, калі яны сапраўдныя, проста прапускае іх без зменаў; у адваротным выпадку, скінуць выключэнне
У абодвух выпадках каналы працуюць з arguments
, якія апрацоўваюцца апрацоўшчыкам маршруту кантролера . Nest устаўляе канал непасрэдна перад выклікам метаду, і канал атрымлівае аргументы, прызначаныя для метаду, і працуе з імі. Любая аперацыя пераўтварэння або праверкі адбываецца ў гэты час, пасля чаго апрацоўшчык маршруту выклікаецца з любымі (патэнцыйна) пераўтворанымі аргументамі.
Nest пастаўляецца з некалькімі ўбудаванымі трубкамі, якімі можна карыстацца адразу. Вы таксама можаце стварыць свае ўласныя трубы. У гэтай главе мы прадставім убудаваныя каналы і пакажам, як прывязаць іх да апрацоўшчыкаў маршрутаў. Затым мы разгледзім некалькі труб, зробленых на заказ, каб паказаць, як можна пабудаваць трубы з нуля.
Убудаваныя трубы
Nest пастаўляецца з дзевяццю трубамі, даступнымі са скрынкі:
ValidationPipe
ParseIntPipe
ParseFloatPipe
ParseBoolPipe
ParseArrayPipe
ParseUUIDPipe
ParseEnumPipe
DefaultValuePipe
ParseFilePipe
Яны экспартуюцца з пакета @nestjs/common
.
Давайце коратка разгледзім выкарыстанне ParseIntPipe
. Гэта прыклад выкарыстання пераўтварэння , калі канвеер забяспечвае пераўтварэнне параметра апрацоўшчыка метаду ў цэлае лік JavaScript (або стварае выключэнне, калі пераўтварэнне не ўдаецца). Далей у гэтай главе мы пакажам простую карыстацкую рэалізацыю для ParseIntPipe
. Прыведзеныя ніжэй прыклады метадаў таксама прымяняюцца да іншых убудаваных каналаў трансфармацыі ( ParseBoolPipe
, ParseFloatPipe
, ParseEnumPipe
, ParseArrayPipe
і ParseUUIDPipe
, якія мы будзем называць каналамі Parse*
у гэтай главе).
Абвязка труб
Каб выкарыстоўваць канал, нам трэба прывязаць асобнік класа канала да адпаведнага кантэксту. У нашым прыкладзе ParseIntPipe
мы хочам звязаць канал з пэўным метадам апрацоўшчыка маршруту і пераканацца, што ён запускаецца перад выклікам метаду. Мы робім гэта з дапамогай наступнай канструкцыі, якую мы будзем называць прывязкай канала на ўзроўні параметраў метаду:
@Get(':id')
async findOne(@Param('id', ParseIntPipe) id: number) {
return this.catsService.findOne(id);
}
Гэта гарантуе выкананне адной з наступных дзвюх умоў: альбо параметр, які мы атрымліваем у метадзе findOne()
з'яўляецца лікам (як чакаецца ў нашым выкліку this.catsService.findOne()
), альбо выключэнне ствараецца перад маршрутам апрацоўшчык называецца.
Напрыклад, выкажам здагадку, што маршрут называецца так:
GET localhost:3000/abc
Nest выкліча наступнае выключэнне:
{
"statusCode": 400,
"message": "Validation failed (numeric string is expected)",
"error": "Bad Request"
}
Выключэнне прадухіліць выкананне цела метаду findOne()
.
У прыведзеным вышэй прыкладзе мы перадаем клас ( ParseIntPipe
), а не асобнік, пакідаючы адказнасць за стварэнне асобніка фрэймворку і дазваляючы ўкараненне залежнасці. Як і ў выпадку з трубамі і ахоўнікамі, замест гэтага мы можам перадаць асобнік н а месцы. Перадача экзэмпляра на месцы карысная, калі мы хочам наладзіць паводзіны ўбудаванага канала шляхам перадачы параметраў:
@Get(':id')
async findOne(
@Param('id', new ParseIntPipe({ errorHttpStatusCode: HttpStatus.NOT_ACCEPTABLE }))
id: number,
) {
return this.catsService.findOne(id);
}
Прывязка іншых каналаў трансфармацыі (усіх каналаў Parse* ) працуе аналагічна. Усе гэтыя каналы працуюць у кантэксце праверкі параметраў маршруту, параметраў радка запыту і значэнняў цела запыту.
Напрыклад, з параметрам радка запыту:
@Get()
async findOne(@Query('id', ParseIntPipe) id: number) {
return this.catsService.findOne(id);
}
Вось прыклад выкарыстання ParseUUIDPipe
для аналізу параметра радка і праверкі, ці з'яўляецца ён UUID.
@@filename()
@Get(':uuid')
async findOne(@Param('uuid', new ParseUUIDPipe()) uuid: string) {
return this.catsService.findOne(uuid);
}
@@switch
@Get(':uuid')
@Bind(Param('uuid', new ParseUUIDPipe()))
async findOne(uuid) {
return this.catsService.findOne(uuid);
}
ParseUUIDPipe()
вы разбіраеце UUID у версіі 3, 4 або 5, калі вам патрабуецца толькі пэўная версія UUID, вы можаце перадаць версію ў параметрах канала. :::Вышэй мы бачылі прыклады прывязкі розных сямействаў убудаваных каналаў Parse*
. Прывязка каналаў праверкі крыху іншая; мы абмяркуем гэта ў наступным раздзеле.
Нестандартныя трубы
Як ужо згадвалася, вы можаце стварыць свае ўласныя трубы. У той час як Nest забяспечвае надзейныя ўбудаваныя ParseIntPipe
і ValidationPipe
, давайце створым простыя карыстальніцкія версіі кожнага з нуля, каб убачыць, як ствараюцца карыстальніцкія каналы.
Мы пачынаем з простага ValidationPipe
. Першапачаткова мы проста прымаем уваходнае значэнне і неадкладна вяртаем тое ж значэнне, паводзячы сябе як функцыя ідэнтыфікацыі.
@@filename(validation.pipe)
import { PipeTransform, Injectable, ArgumentMetadata } from '@nestjs/common';
@Injectable()
export class ValidationPipe implements PipeTransform {
transform(value: any, metadata: ArgumentMetadata) {
return value;
}
}
@@switch
import { Injectable } from '@nestjs/common';
@Injectable()
export class ValidationPipe {
transform(value, metadata) {
return value;
}
}
PipeTransform<T, R>
- гэта агульны інтэрфейс, які павінен быць рэалізаваны любым каналам. Агульны інтэрфейс выкарыстоўвае T
, каб паказаць тып уваходнага value
, і R
, каб паказаць тып вяртання метаду transform()
. :::Кожны канал павінен рэаліз аваць метад transform()
, каб выканаць кантракт інтэрфейсу PipeTransform
. Гэты метад мае два параметры:
value
metadata
Параметр value
- гэта аргумент метаду, які апрацоўваецца ў дадзены момант (да яго атрымання метадам апрацоўкі маршруту), а metadata
- гэта метаданыя аргумента метаду, які апрацоўваецца ў цяперашні час. Аб'ект метададзеных мае наступныя ўласцівасці:
export interface ArgumentMetadata {
type: 'body' | 'query' | 'param' | 'custom';
metatype?: Type<unknown>;
data?: string;
}
Гэтыя ўласцівасці апісваюць аргумент, які зараз апрацоўваецца.
type | Паказвае, ці з'яўляецца аргумент целам @Body() , запытам @Query() , параметрам @Param() або карыстальніцкім параметрам (больш падрабязна тут ). |
metatype | Дае метатып аргумента, напрыклад, String . Заўвага: значэнне undefined , калі вы прапусціце дэкларацыю тыпу ў сігнатуры метаду апрацоўшчыка маршруту або выкарыстоўваеце банальны JavaScript. |
data | Радок, перададзены дэкаратару, напрыклад @Body('string') . Гэта undefined , калі вы пакінеце круглыя дужкі дэкаратара пустымі. |
:::папярэджанне Папярэджанне Інтэрфейсы TypeScript знікаюць падчас транспіляцыі. Такім чынам, калі тып параметра метаду аб'яўлены як інтэрфейс замест класа, значэннем metatype
будзе Object
. :::