Давайте перепишем CNode с помощью Nestjs (Часть 1)

Node.js база данных JavaScript NPM

задний план

В этой статье я буду использоватьNest.jsпостроитьCNode.

Почему эта статья? мне нравитьсяNodeJs, хотя мойNodeJsсредний уровень. Но я все еще использую его для документирования процесса обучения.

Недавно я обнаружилNest.jsФреймворк, который эффективно решает сложную проблему в проектах Nodejs: архитектуру.NestРазработан для предоставления готовых приложений, которые упрощают создание легко тестируемых, расширяемых, слабосвязанных и простых в обслуживании приложений.Nest.jsБудуTypeScriptпредставлятьNode.jsв и на основеExpressупаковка. Итак, я хочу использоватьNest.jsпопробуй написатьCNode. (ps: в настоящее время CNode принимаетEggпишите) Квикстарта на эту тему не нашел, поэтому приведу свою практику, которую вы легко сможете распространить на свой проект.

Цель этой статьи не в том, чтобы представить Nest.js. Для тех, кто не знаком с Nest.js: это платформа для создания веб-приложений Node.js. Хотя Node.js уже включает множество библиотек для разработки веб-приложений, ни одна из них не затрагивает одну из самых важных тем: архитектуру.

А теперь пристегните ремни, мы идем.

Что такое гнездо

nest_logo

Nestявляется мощнымNode webРамка. Это поможет вам легко создавать эффективные, масштабируемые приложения. он использует современныеJavaScript,использоватьTypeScriptстроить, комбинироватьOOP(объектно-ориентированное программирование) иFPЛучшая концепция (функциональное программирование).

Это не просто еще один фреймворк. Вам не нужно ждать большого сообщества, потому чтоNestОн использует замечательную, популярную известную библиотеку --Expressа такжеsocket.ioЭто означает, что вы можете быстро начать использовать фреймворк, не беспокоясь о сторонних плагинах.

авторKamil MyśliwiecПервоначальное намерение:

JavaScript прекрасен, Node.js дал нам возможность использовать этот язык и на стороне сервера, на этой платформе много замечательных библиотек, хелперов и инструментов, но ни один из них не решает главную проблему — архитектуру. Это почему я решил создать фреймворк Nest.

важный:NestполученоJava Springа такжеAngularвдохновение. если вы использовалиJava SpringилиAngularВ освоении будет очень легко, я сам постоянно им пользуюсьAngular.

Основные концепции Nest

Основная концепция Nest — предоставить архитектуру, которая поможет разработчикам достичь максимального разделения уровней и повысить уровень абстракции в приложениях.

Обзор архитектуры

NestУсыновленныйES6а такжеES7Особенности (decorator, async/await). Если вы хотите использовать их, вам нужно использоватьBabelилиTypeScriptПеревести вes5.

NestПо умолчанию используетсяTypeScript, также можно использовать напрямуюJavaScript, но это не имеет смысла.

если вы использовалиAngular, вы найдете эту статью очень знакомой, потому что большинство из них написаны одинаково. Неважно, использовали ли вы их, я веду вас изучать их вместе.

Модуль Модуль

использоватьNest, вы можете естественным образом разделить свой код на независимые и повторно используемые модули.Nestмодуль - это@Module()Класс декоратора. Этот декоратор предоставляет метаданные, которые платформа использует для организации структуры приложения.

каждыйNestПриложения имеют корневой модуль, обычно называемыйAppModule. Корневой модуль обеспечивает механизм начальной загрузки, используемый для запуска приложения. Приложение обычно содержит множество функциональных модулей.

картинаJavaScriptКак модули,@ModuleТакже доступен из др.@Moduleимпортировать функции в и разрешать экспортировать собственные функции для других@Moduleиспользовать. Например, чтобы использовать в своем приложенииnestкоторый предоставилmongooseДля работы функции необходимо импортироватьMongooseModule.

Организация вашего кода в четкие функциональные модули может помочь в управлении разработкой сложных приложений и обеспечить многократное использование проектов. Кроме того, эта методика позволяет использовать динамическую нагрузку,MongooseModuleзаключается в использовании этой технологии.

@ModuleДекоратор принимает объект, свойства которого описывают модуль:

Атрибуты описывать
providers Зависит отNestСлужба, созданная инжектором, может совместно использоваться этим модулем.
controllers Содержит созданный набор контроллеров.
imports Список модулей, который импортирует поставщиков, необходимых в этом модуле.
exports Экспорт этого модуля может быть использован другими модулямиprovidersуслуги в.

@ModuleКонтекст компиляции объявляется для набора контроллеров, который фокусируется на области приложения, рабочем процессе или тесно связанном наборе возможностей.@ModuleЕго контроллер может быть связан с набором связанного кода, такого как служба, для формирования функционального блока.

Как организовать схему структуры модуля

Корневой модуль AppModule

  • Базовые модули CoreModule (регистрация промежуточного ПО, фильтры, конвейеры, охранники, перехватчики, декораторы и т. д.)
  • Общие модули SharedModule (зарегистрированные сервисы, mongodb, redis и т. д.)
  • Модуль конфигурации ConfigModule (конфигурация системы)
  • FeatureModule Функциональные модули (бизнес-модули, такие как пользовательские модули, модули продукта и т. д.)

существуетNest, модули по умолчанию являются одноэлементными, поэтому один и тот же экземпляр любого поставщика может совместно использоваться несколькими модулями. Совместное использование модулей не требует усилий.

Общий вид относительно чистый и освежающий, как и я.AngularРазделение модулей, которое использовалось в проекте.

Если у вас есть лучшие предложения, добро пожаловать, чтобы общаться и совершенствоваться со мной.

Контроллер Контроллер

Контроллер отвечает за обработку параметров запроса, переданных клиентом, и возврат данных ответа клиенту.Популярным моментом является маршрутизация.Router.

Для создания базового контроллера мы используем@Controllerдекоратор. Они связывают классы с базовыми метаданными, поэтомуNestЗнать, как сопоставлять контроллеры с соответствующими маршрутами.

@ControllerТребуется определить базовый контроллер.@Controller('Router Prefix')является необязательным префиксом для каждого маршрута, зарегистрированного в классе. Использование префикса позволяет избежать повторного использования самого себя, когда все маршруты имеют общий префикс.

@Controller('user')
export class UserController {
    @Get()
    findAll() {
        return [];
    }

    @Get('/admin')
    admin() {
        return {};
    }
}
//  findAll访问就是  xxx/user
//  admin访问就是    xxx/user/admin

Контроллер — это относительно основная функция, вокруг которой строится весь бизнес.NestОн также предоставляет множество связанных декораторов.Далее я представлю их один за другим.Это просто краткое описание, а их использование будет представлено позже в реальном бою.

Запрос объекта представляет собой запрос HTTP и запрос с параметром строки запроса, заголовками HTTP, свойства, но в большинстве случаев не нужно их вручную получить их. Мы можем использовать преданныйdecorator,Например@Body()или@Query(), они доступны из коробки. Нижеdecoratorс обычнымExpressсравнение объектов.

Давайте сначала поговорим о декораторе параметра метода:

имя декоратора описывать
@Request() вести перепискуExpressизreq, также можно сократить@req
@Response() вести перепискуExpressизres, также можно сократить@res
@Next() вести перепискуExpressизnext
@Session() вести перепискуExpressизreq.session
@Param(param?: string) вести перепискуExpressизreq.params
@Body(param?: string) вести перепискуExpressизreq.body
@Query(param?: string) вести перепискуExpressизreq.query
@Headers(param?: string) вести перепискуExpressизreq.headers

Давайте сначала поговорим о декораторе метода:

имя декоратора описывать
@Post() вести перепискуExpressизPostметод
@Get() вести перепискуExpressизGetметод
@Put() вести перепискуExpressизPutметод
@Delete() вести перепискуExpressизDeleteметод
@All() вести перепискуExpressизAllметод
@Patch() вести перепискуExpressизPatchметод
@Options() вести перепискуExpressизOptionsметод
@Head() вести перепискуExpressизHeadметод
@Render() вести перепискуExpressизres.renderметод
@Header() вести перепискуExpressизres.headerметод
@HttpCode() вести перепискуExpressизres.statusметод, который можно комбинировать сHttpStatusперечислить

Вышеупомянутые в основном декораторы контроллера.Некоторые общие параметры HTTP-запроса необходимо использовать вместе с соответствующими декораторами и параметрами методов.

Что касается возврата данных ответа,NestТакже доступны 2 решения:

  1. непосредственно вернутьJavaScriptобъект или массив, он будет автоматически разрешен кJSON. Когда мы возвращаем строку,NestПросто отправьте строку, не пытаясь ее разобрать. По умолчанию код состояния ответа всегда200,
    ноPOSTза исключением запросов, которые используют201. можно использовать@HttpCode(HttpStatus.xxxx)Декораторы могут легко изменить это поведение.

  2. Мы можем использовать конкретный объект ответа библиотеки, мы можем использовать здесь@res() модификатор внедряет объект в сигнатуру функции,
    res.status(HttpStatus.CREATED).send()илиres.status(HttpStatus.OK).json([])ЖдатьExpressизresметод.

Уведомление: Запрещено использовать эти два метода одновременно, если использовать оба, то этот маршрут работать не будет. Если вы обнаружите, что маршрут не отвечает, когда вы его используете, проверьте, нет ли какого-либо смешанного использования.Если это нормально, рекомендуется вернуться к первому методу.

Контроллер должен быть зарегистрирован в метаданных модуля.controllersнормально работать.

Что касается обработки исключений контроллера, фильтр будет объяснен позже.

Внедрение зависимостей от провайдера

Служба — это широкое понятие, которое включает любое значение, функцию или свойство, требуемое приложением. Услуга в узком смысле — это класс с четко определенной целью. Он должен делать что-то конкретное и делать это хорошо.

NestОтдельные контроллеры и сервисы для улучшения модульности и возможности повторного использования.

Отделив связанные с логикой функции в контроллере от других типов обработки, вы можете сделать класс контроллера компактнее и эффективнее. В идеале работа контроллера состоит в том, чтобы объявлять декораторы и отвечать данными, и ничего более. Он должен обеспечивать мост запроса и ответа, чтобы действовать как посредник между представлением (отображаемым шаблоном) и логикой приложения (которая обычно содержит некоторое понятие модели).

Контроллеру не нужно определять что-либо вроде получения данных от клиента, проверки ввода пользователя или записи журналов непосредственно в консоль. Вместо этого делегируйте эти задачи различным службам. Определяя различные задачи обработки в внедряемых классах обслуживания, вы можете сделать их доступными для любого контроллера. Вы также можете сделать свое приложение более адаптируемым, внедрив разных поставщиков одной и той же службы в разные среды.

NestЭти принципы не соблюдаются. Это просто упрощает разложение логики вашего приложения на сервисы посредством внедрения зависимостей и делает эти сервисы доступными для отдельных контроллеров.

Контроллеры являются потребителями служб, то есть вы можете внедрить службу в контроллер и предоставить классу контроллера доступ к классу службы.

Тогда сервис — это провайдер, в принципе почти все можно рассматривать как провайдер — сервис, репозиторий, фабрику, помощника и т.д. Они могут быть внедрены в зависимости конструктивной функцией, что означает, что они могут создавать различные отношения друг с другом.

существуетNest, чтобы определить класс как службу, используйте@Injectableдекоратор для предоставления метаданных, чтобыNestЕго можно внедрить в контроллер как зависимость.

Аналогично, также используйте@InjectableДекоратор, чтобы указать, что контроллер или другой класс (например, другая служба, модуль и т. д.) имеет зависимость. Зависимость не обязательно должна быть службой, это может быть функция или значение и т. д.

Инъекция зависимостей (часто сокращенная ди) вводится вNestВ кадре используется для использования его везде, чтобы обеспечить желаемую услугу или другие вещи для вновь созданного контроллера.

Инжектор является основным механизмом. Вам не нужно создавать его самостоятельноNestинжектор.NestВо время запуска для вас создается полный инжектор уровня приложения.

Инжектор поддерживает контейнер экземпляров зависимостей, которые он создал, и максимально повторно использует их.

Провайдеры — это рецепты для создания зависимостей. Для сервисов это обычно сам класс сервиса. Любой класс, который вы используете в своем приложении, должен зарегистрировать поставщика в инжекторе приложения, чтобы инжектор мог использовать его для создания новых экземпляров.

О внедрении зависимостей, интерфейсном фреймворкеAngularНаверное, самый известный, вы можете увидетьздесьпредставлять.

// 用户服务
import { Injectable } from '@nestjs/common';

interface User {}

@Injectable()
export class UserService {
  private readonly user: User[] = [];

  create(cat: User) {
    this.user.push(User);
  }

  findAll(): User[] {
    return this.user;
  }
}

// 用户控制器
import { Controller, Get, Post, Body } from '@nestjs/common';
import { UserService } from './user.service';

@Controller('user')
export class UserController {
  constructor(private readonly userService: UserService) {}

  @Post()
  async create(@Body() createUserDto: CreateUserDto) {
    this.userService.create(createUserDto);
  }

  @Get()
  async findAll(): Promise<User[]> {
    return this.userService.findAll();
  }
}

индивидуальный сервис

Мы можем не только использовать@Injectable()Существует три других способа определить услугу:value,class,factory.
Это то же самое, что и Angular, по умолчанию@Injectable()Чтобы определить услугуclass.

использоватьvalue:

const customObject = {};
@Module({
    controllers: [ UsersController ],
    components: [
        { provide: UsersService, useValue: customObject }
    ],
})

Уведомление:useValueможет быть любым значением, в этом модулеNestположитcustomObjectа такжеUsersServiceСоответственно, вы также можете использовать его как тестовый дубль (модульный тест).

использоватьclass:

import { UserService } from './user.service';
const customObject = {};
@Module({
    controllers: [ UsersController ],
    components: [
        { provide: UsersService, useClass: UserService }
        OR
        UserService
    ],
})

Уведомление: Только в этом модуле с использованием выбранного, более конкретного класса,useClassможет быть иprovideто же самое, если не то же самое, чтоuseClassзаменятьprovide. Простое понимание изменения методов, без изменения имени метода, обычно используемого для работы с внедрением зависимостей в разных средах.

использоватьfactory:

@Module({
    controllers: [ UsersController ],
    components: [
        ChatService,
        {
            provide: UsersService,
            useFactory: (chatService) => {
                return Observable.of('customValue');
            },
            inject: [ ChatService ]
        }
    ],
})

Уведомление: хочет предоставить значение, которое должно быть вычислено с использованием другого компонента (или пользовательского атрибута пакета) хочет предоставить асинхронные значения (возвращают только наблюдаемые или обещанные значения), такие как соединение с базой данных.injectзависимые услуги,provideзарегистрированное имя,useFactoryспособ обработки,useFactoryпараметры иinjectПорядок массива инъекций такой же.

если мыprovideЧто делать, если регистрационное имя не служба, а строкаkey, также очень часто используется.

@Module({
    controllers: [ UsersController ],
    components: [
        { provide: 'isProductionMode', useValue: false }
    ],
})

Чтобы использовать выбранную пользовательскую строкуkey, вы должны сообщить Nest, что вам нужно использовать@Inject()декоратор, например:

import { Component, Inject } from 'nest.js';

@Component()
class SampleComponent {
    constructor(@Inject('isProductionMode') private isProductionMode: boolean) {
        console.log(isProductionMode); // false
    }
}

Существует также круглая яма зависимости, и реальный бой покажет, как избежать и решить эту яму.

Служба должна быть зарегистрирована в метаданных модуля.providersнормально работать. Если он должен использоваться другими модулями, его необходимо добавить вexportsсередина.

ПО промежуточного слоя

Промежуточное ПО — это функции, которые вызываются перед обработчиками маршрутов. Функции промежуточного ПО имеют доступ к объектам запроса и ответа, а также к следующей функции промежуточного ПО в цикле запроса-ответа приложения. Следующая промежуточная функция обычно вызываетсяnextпеременное представление. существуетExpressПромежуточное ПО очень известно.

по умолчанию,NestЭквивалентное представление промежуточного программного обеспеченияExpressпромежуточное ПО. а такжеExpressФункция промежуточного программного обеспечения аналогична, функция промежуточного программного обеспечения может выполнять следующие задачи.

  • выполнить любой код.
  • Внесите изменения в объекты запроса и ответа.
  • Цикл запрос-ответ заканчивается.
  • Вызовите следующую функцию промежуточного программного обеспечения в стеке.
  • Если текущая промежуточная функция не завершает цикл запрос-ответ, она должна вызватьnext()Передать управление следующей промежуточной функции. В противном случае запрос будет приостановлен.

просто понятьNestпромежуточное ПОExpressПромежуточное ПО упаковано. Преимущество в том, что пока вы хотите использовать промежуточное программное обеспечение, вы можете сразу искатьExpressПромежуточное ПО готово к использованию. Это очень удобно.

NestПромежуточное ПО — это либо функция, либо@Injectable()Класс декоратора. класс должен реализоватьNestMiddlewareинтерфейсы, а функции не предъявляют особых требований.

// 实现一个带有`@Injectable()`装饰器的类打印中间件
import { Injectable, NestMiddleware, MiddlewareFunction } from '@nestjs/common';

@Injectable()
export class LoggerMiddleware implements NestMiddleware {
  resolve(...args: any[]): MiddlewareFunction {
    return (req, res, next) => {
      console.log('Request...');
      next();
    };
  }
}

Как использовать, есть два способа:

  1. Промежуточное ПО может быть зарегистрировано глобально
async function bootstrap() {
  // 创建Nest.js实例
  const app = await NestFactory.create(AppModule, application, {
    bodyParser: true,
  });
  // 注册中间件
  app.use(LoggerMiddleware());
  // 监听3000端口
  await app.listen(3000);
}
bootstrap();
  1. Промежуточное ПО может быть зарегистрировано локально в модулях
export class CnodeModule implements NestModule {
  configure(consumer: MiddlewareConsumer) {
    consumer
      .apply(LoggerMiddleware)
      .with('ApplicationModule')
      .exclude(
        { path: 'user', method: RequestMethod.GET },
        { path: 'user', method: RequestMethod.POST },
      )
      .forRoutes(UserController);
  }
}

// or

export class CnodeModule implements NestModule {
  configure(consumer: MiddlewareConsumer) {
    consumer
      .apply(LoggerMiddleware)
      .forRoutes('*');
  }
}

// 1. with是提供数据,resolve里可以获取,exclude指定的路由,forRoutes注册路由,
// 2. forRoutes传递'*'表示作用全部路由

Уведомление: Они зарегистрированы в разных местах, и затрагиваемые маршруты тоже разные.Глобальная регистрация влияет на все маршруты, а локальная регистрация влияет только на маршруты под текущим маршрутом.

фильтр Фильтр исключений

Уровень фильтра исключений отвечает за обработку всех выброшенных исключений в приложении. При обнаружении необработанного исключения конечный пользователь получит соответствующий удобный ответ.

Показать ответ по умолчаниюJSONИнформация

{
  "statusCode": 500,
  "message": "Internal server error"
}

Используйте низкоуровневый фильтр

@Post()
async create(@Body() createCatDto: CreateCatDto) {
  throw new HttpException('Forbidden', HttpStatus.FORBIDDEN);
}

HttpException принимает 2 параметра:

  • Содержимое сообщения, которое может быть строковым сообщением об ошибке или объектом.{status: 状态码,error:错误消息}
  • код состояния

Очень хлопотно писать столько каждый раз, тогда фильтр также поддерживает расширение и настройку объекта фильтра ярлыков.

export class ForbiddenException extends HttpException {
  constructor() {
    super('Forbidden', HttpStatus.FORBIDDEN);
  }
}

Вы можете использовать его напрямую:

@Post()
async create(@Body() createCatDto: CreateCatDto) {
  throw new ForbiddenException('Forbidden');
}

Не так ли удобнее.

NestДает нам много этих быстрых и распространенных ошибок состояния HTTP:

  • BadRequestException 400
  • UnauthorizedException 401
  • ForbiddenException 403
  • NotFoundException 404
  • NotAcceptableException 406
  • RequestTimeoutException 408
  • ConflictException 409
  • GoneException 410
  • PayloadTooLargeException 413
  • UnsupportedMediaTypeException 415
  • UnprocessableEntityException 422
  • InternalServerErrorException 500
  • NotImplementedException 501
  • BadGatewayException 502
  • ServiceUnavailableException 503
  • GatewayTimeoutException 504

Основы обработчика исключений хороши, но иногда вам может понадобиться полный контроль над уровнем исключений, например, добавить ведение журнала или использовать другойJSONШаблоны основаны на некоторых выбранных факторах. Я сказал раньше,NestДайте нам встроенный шаблон ответного ответа.Это неприемлемо.Что нам делать с настройкой?NestДайте нам возможность расшириться.

import { ExceptionFilter, Catch, ArgumentsHost } from '@nestjs/common';
import { HttpException } from '@nestjs/common';

@Catch(HttpException)
export class HttpExceptionFilter implements ExceptionFilter {
  catch(exception: HttpException, 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,
      });
  }
}

он возвращаетExpressМетодыresponse, чтобы настроить собственный формат исключения ответа.

Как использовать, есть четыре способа:

  1. непосредственный@UseFilters()Используется в декораторе для обработки результата ответа текущего маршрута.
@Post()
@UseFilters(HttpExceptionFilter | new HttpExceptionFilter())
async create(@Body() createCatDto: CreateCatDto) {
  throw new ForbiddenException();
}
  1. непосредственный@UseFilters()Используется в декораторе для направления всех результатов ответа на текущий контроллер.
@UseFilters(HttpExceptionFilter | new HttpExceptionFilter())
export class CatsController {}
  1. Глобальная регистрация с использованием встроенных методов экземпляраuseGlobalFilters, который действует на весь проект. Этот тип фильтра является более общим и рекомендует глобальную регистрацию.
async function bootstrap() {
  const app = await NestFactory.create(ApplicationModule);
  app.useGlobalFilters(new HttpExceptionFilter());
  await app.listen(3000);
}
bootstrap();

трубка

Конвейеры могут проверять тип, структуру объекта или данные сопоставления с параметрами вашего запроса в соответствии с определенными условиями. Конвейер — это чистая функция, и он не должен выбирать или вызывать какие-либо сервисные операции из базы данных.

Определите простой конвейер:

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

@Injectable()
export class ValidationPipe implements PipeTransform {
  transform(value: any, metadata: ArgumentMetadata) {
    return value;
  }
}

трубы используются@Injectable()Класс комментария декоратора. Должен быть реализованPipeTransformинтерфейс, конкретный код находится вtransformреализовать, это иAngularТак же, как.

NestОбрабатывает проверку данных запроса, создает исключения, когда данные неверны, и использует фильтры для их обнаружения.

NestДля нас встроены 2 основных конвейера: проверка данныхValidationPipe, преобразование данныхParseIntPipe.

использоватьValidationPipeнужно сотрудничатьclass-validator class-transformer, если вы их не устанавливаете, вы используетеValidationPipeсообщит об ошибке.

намекать:ValidationPipeВозможна не только проверка данных запроса, но и преобразование типов данных, что можно увидеть на официальном сайте.

Как использовать, есть четыре способа

  1. непосредственный@Body()Используется в декораторе, используется только текущий параметр body
// 用户控制器
import { Controller, Get, Post, Body } from '@nestjs/common';
import { UserService } from './user.service';

@Controller('user')
export class UserController {
  constructor(private readonly userService: UserService) {}
  @Post()
  async create(@Body(ValidationPipe | new ValidationPipe()) createUserDto: CreateUserDto) {
    this.userService.create(createUserDto);
  }
}
  1. существует@UsePipes()Используется в декораторе для обработки всех параметров запроса текущего маршрута.
// 用户控制器
import { Controller, Get, Post, Body } from '@nestjs/common';
import { UserService } from './user.service';

@Controller('user')
export class UserController {
  constructor(private readonly userService: UserService) {}
  @Post()
  @UsePipes(ValidationPipe | new ValidationPipe())
  async create(@Body() createUserDto: CreateUserDto) {
    this.userService.create(createUserDto);
  }
}
  1. существует@UsePipes()Используется в декораторе для маршрутизации всех параметров запроса к текущему контроллеру.
// 用户控制器
import { Controller, Get, Post, Body } from '@nestjs/common';
import { UserService } from './user.service';

@Controller('user')
@UsePipes(ValidationPipe | new ValidationPipe())
export class UserController {
  constructor(private readonly userService: UserService) {}
  @Post()
  async create(@Body() createUserDto: CreateUserDto) {
    this.userService.create(createUserDto);
  }
}
  1. Глобальная регистрация с использованием встроенных методов экземпляраuseGlobalPipes, который действует на весь проект. Этот конвейер является более общим и рекомендует глобальную регистрацию.
async function bootstrap() {
  const app = await NestFactory.create(ApplicationModule);
  app.useGlobalPipes(new ValidationPipe());
  await app.listen(3000);
}
bootstrap();

ТакcreateUserDtoКак играть, фактический боевой туториал объяснит это позже, здесь он не будет расширяться.

@Get(':id')
async findOne(@Param('id', ParseIntPipe | new ParseIntPipe()) id) {
  return await this.catsService.findOne(id);
}

ParseIntPipeЕго также очень просто использовать, то есть преобразовать строку в число. Он также чаще используется, особенно когда ваш идентификатор представляет собой строковое число, используйтеget,put,patch,deleteОжидание запроса, особенно полезно, когда есть id.
Вы также можете выполнять пейджинговую обработку, которая будет использоваться позже в реальном бою, что будет подробно объяснено.

Сторожить

Охранник может выполнять аутентификацию разрешения. Если у вас нет разрешения, он может отказать вам в доступе к этому маршруту и ​​вернуться по умолчанию.403ошибка.

Определите простой конвейер:

import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common';
import { Observable } from 'rxjs';

@Injectable()
export class AuthGuard implements CanActivate {
  canActivate(
    context: ExecutionContext,
  ): boolean | Promise<boolean> | Observable<boolean> {
    const request = context.switchToHttp().getRequest();
    return validateRequest(request);
  }
}

охрана используется@Injectable()Класс, аннотированный декоратором. должны быть реализованыCanActivateинтерфейс, конкретный код находится вcanActivateМетод реализован и возвращает логическое значение, true указывает на разрешение, а false выдает ошибку исключения 403. Это написание иAngularТак же, как.

Как использовать, есть два способа

  1. непосредственный@UseGuards()Используется в декораторе для маршрутизации всех параметров запроса к текущему контроллеру.
@Controller('cats')
@UseGuards(RolesGuard | new RolesGuard())
export class CatsController {}
  1. Глобальная регистрация с использованием встроенных методов экземпляраuseGlobalGuards, который действует на весь проект.
const app = await NestFactory.create(ApplicationModule);
app.useGlobalGuards(new RolesGuard());

Если вы не выполняете операции аутентификации, связанные с управлением правами, эта функция вам практически не нужна. Еще полезная абстракция. Мы также будем использовать эту функцию в этом реальном боевом проекте.

Перехватчик Перехватчик

Перехватчик — это специальная и мощная функция, похожая на АОП-аспектное программирование, и эта технология также была опробована во внешнем программировании.Например, различные библиотеки HTTP-запросов предоставляют аналогичные функции. знаменитый кадрAngularHTTP-модуль фреймворка. У известных библиотек есть старыеjqueryи модныйaxiosЖдать.

Определите простой перехватчик:

import { Injectable, NestInterceptor, ExecutionContext } from '@nestjs/common';
import { Observable } from 'rxjs';
import { tap } from 'rxjs/operators';

@Injectable()
export class LoggingInterceptor implements NestInterceptor {
  intercept(
    context: ExecutionContext,
    call$: Observable<any>,
  ): Observable<any> {
    console.log('Before...');
    const now = Date.now();
    return call$.pipe(
      tap(() => console.log(`After... ${Date.now() - now}ms`)),
    );
  }
}

Используется перехватчик@Injectable()Класс, аннотированный декоратором. должны быть реализованыNestInterceptorинтерфейс, конкретный код находится вinterceptреализация метода возвращаетObservable, это письмо иAngularТак же, как.

Что может перехватчик:

  • Привязать дополнительную логику до/после выполнения метода
  • Преобразование результата, возвращаемого функцией
  • Преобразование исключений, выброшенных из функций
  • Расширьте базовое поведение функции
  • Полное покрытие функции зависит от выбранных условий (например, кэширование).

Как использовать, есть три способа

  1. непосредственный@UseInterceptors()Она используется в декораторе для работы с текущим маршрутом, а также может передавать параметры, требует специальной обработки, может быть написана как функция высшего порядка, а также может использовать внедрение зависимостей.
@Post('upload')
@UseInterceptors(FileFieldsInterceptor | FileFieldsInterceptor([
  { name: 'avatar', maxCount: 1 },
  { name: 'background', maxCount: 1 },
]))
uploadFile(@UploadedFiles() files) {
  console.log(files);
}
  1. непосредственный@UseInterceptors()Он используется в декораторе и действует на текущую маршрутизацию контроллера, не может передавать параметры, но можно использовать внедрение зависимостей.
@UseInterceptors(LoggingInterceptor | new LoggingInterceptor())
export class CatsController {}
  1. Глобальная регистрация с использованием встроенных методов экземпляраuseGlobalInterceptors, который действует на весь проект.
const app = await NestFactory.create(ApplicationModule);
app.useGlobalInterceptors(new LoggingInterceptor());

Перехватчики могут выполнять множество функций, таких как обработка кэша, преобразование данных ответа, преобразование захвата исключений, ошибка тайм-аута ответа и журнал ответов на запросы печати. Мы также будем использовать эту функцию в этом реальном боевом проекте.

Суммировать

Модули — это базовые блоки, разделенные бизнес-логикой, включая контроллеры и сервисы. Контроллер — это часть, которая обрабатывает данные запросов и ответов, а служба — это часть, которая обрабатывает фактическую бизнес-логику.

Промежуточное ПО — это уровень обработки данных перед обработчиком обработки маршрутизации. Его можно зарегистрировать только в модуле или глобально. Его можно использовать для промежуточного ПО для обработки журналов, промежуточного ПО для аутентификации пользователей и т. д. Промежуточное ПО такое же, как экспресс-промежуточное ПО, поэтому оно может получить доступ ко всему запросу и ответу.В этом контексте службы с областью действия модуля могут быть внедрены зависимостями. Глобальная регистрация может быть только чистой функцией или функцией более высокого порядка.

Конвейер — это обработка потока данных.Обработка данных выполняется после промежуточного ПО и перед обработкой маршрутизации.Его могут использовать классы,методы,параметры методов и глобальная регистрация в контроллере.Это может быть только чистая функция. Может выполнять проверку данных, преобразование данных и другую обработку данных.

Guard должен решить, может ли запрос достичь соответствующего обработчика маршрута, может ли он знать контекст выполнения текущего маршрута, может ли он использоваться классом, методом и глобальной регистрацией в контроллере, и может ли он использоваться в качестве роль охранника.

Перехватчик должен обрабатывать связанную логику до и после входа в контроллер.Он может знать контекст выполнения текущего маршрута.Он может использоваться классами, методами и глобальной регистрацией в контроллере.Он может вести журнал,обработку транзакций,обработку исключений. и формат данных ответа.

Фильтр предназначен для захвата информации об ошибке и возврата ответа клиенту. Его можно использовать для классов, методов и глобальной регистрации в контроллере, а также для настройки формата исключения ответа.

Промежуточное ПО, фильтры, конвейеры, охранники, перехватчики — вот несколько вещей, которые легко спутать. Что у них общего, так это промежуточный уровень абстракции, который подключен к контроллеру, но их обязанности различны.

Глобальные пайпы, охранники, фильтры и перехватчики слабо связаны с любыми модулями. Они не могут внедрить какие-либо службы, потому что они не принадлежат ни одному модулю. Вы можете использовать область контроллера, область метода или вспомогательную область, поддерживаемую только конвейерами, другие, кроме промежуточного программного обеспечения, которые являются областью модуля, являются областью контроллера и областью метода.

фокус: Они написаны в примере. Обратите внимание, что глобальные каналы, охранники, фильтры и перехватчики могут быть только новыми. Глобальное промежуточное ПО — это чистая функция. Глобальные каналы, охранники, фильтры и перехватчики нельзя использовать для внедрения зависимостей. Регистрация модуля промежуточного ПО также не может использовать new, но можно использовать внедрение зависимостей. Каналы, охранники, фильтры и перехватчики могут быть зарегистрированы локально с использованием новых имен и имен классов, за исключением каналов, в которые можно вводить зависимости. Перехватчики и охранники могут быть написаны как высокоуровневые методы для передачи параметров в целях настройки.

Защитные ограждения труб, фильтров и перехватчиков имеют свои особые обязанности. Интерцепторы и ограждения объединены с модулями, а трубы и фильтры работают вне зоны модуля. Задача конвейера заключается в проверке типа, структуры объекта или сопоставления данных с определенными условиями. Задача фильтра — ловить различные ошибки и возвращать их клиенту. Каналы — неподходящее место для выбора или вызова какой-либо службы из базы данных. Перехватчики, с другой стороны, не должны проверять схемы объектов или украшать данные. Если требуется перезапись, она должна быть вызвана вызовом службы из базы данных. Охранник решает, какие маршруты доступны, и берет на себя вашу ответственность за проверку.

Тогда вас должно больше всего беспокоить, в каком порядке они выполняются:

客户端请求 ---> 中间件 ---> 守卫 ---> 拦截器之前 ---> 管道 ---> 控制器处理并响应 ---> 拦截器之后 ---> 过滤器

Давайте посмотрим на 2 картинки,

Запрос возвращает результат ответа:

hdvo ug9_58 g 9o_n n 7o

Запрос возвращает исключение ответа:

nmzgsgsc5ynm_ghfsxzl5jh

Hello World

Изучение языка и технологии начинается сHello WorldВ начале мы также идем от нуля кHello Worldначать учитьсяNestпутешествие

Подготовьте необходимую среду разработки и инструменты

рекомендоватьnvmсправлятьсяnodejsВерсия, в соответствии с их компьютером, чтобы загрузить соответствующую версию.

  1. Подготовьте среду:Nodejsv8+ (текущая версия v10+, должна быть 8 или выше, высокая поддержка es2015)
  2. Подготовьте базу данных:mongodbv3+ (текущая версия v4+)
  3. Подготовьте базу данных:redisv3+ (текущая версия v3+)
  4. Редактор подготовки:vs codeПоследняя версия может быть (родная windows v1.26)
  5. vs codeРекомендуемые плагины: (другие плагины не обязательны)
    • Отладчик для Chrome -- отладка
    • ejs -- подсветка файла ejs
    • Украсить -- форматирование кода
    • DotENV -- подсветка файла .env
    • Jest - встроенная поддержка тестовой среды по умолчанию
    • TSLint -- проверка синтаксиса ts
    • Герой TypeScript — советы ТС
    • vscode-icons -- icons
  6. Рекомендуется использовать несколько полезных инструментов:
    • Почтальоны — артефакт тестирования API
    • Robomongo — графический инструмент mongodb
    • Redis Desktop Manager — графический инструмент Redis
    • Cmder — артефакт командной строки Windows

Ресурсы, связанные с Nest

  1. Официальный сайт:nestjs.com
  2. Документация:docs.nestjs.com
  3. Китайский документ:docs.nestjs.cn
  4. Гитхаб:github.com/nestjs/nest
  5. Версия: Текущая стабильная версия v5.1.0
  6. Интерфейс командной строки:GitHub.com/nest JS / Гнездо ...

nest-cli

nest-cliЯвляетсяnestЛеса проекта. Предоставляет нам модуль инициализации, который позволяет нам сделать это быстроHello WorldФункция.

Установить

npm i -g @nestjs/cli

Общие команды:

новый (аббревиатура: n) для создания нового проекта
$ nest new my-awesome-app
OR
$ nest n my-awesome-app
generate (аббревиатура: g) для создания файлов
  • class (аббревиатура: cl) класс
  • контроллер (аббревиатура: со) контроллер
  • декоратор (аббревиатура: д) декоратор
  • исключение (аббревиатура: e) перехват исключения
  • фильтр (аббревиатура: f) фильтр
  • шлюз (аббревиатура: га) шлюз
  • охрана (аббревиатура: гу) охранять
  • перехватчик (аббревиатура: i) перехватчик
  • промежуточное ПО (аббревиатура: mi) промежуточное ПО
  • модуль (аббревиатура: мо) модуль
  • труба (аббревиатура: пи) труба
  • провайдер (аббревиатура: пр) поставщик
  • сервис (аббревиатура: s) обслуживание

Создайте файл службы пользователей

$ nest generate service users
OR
$ nest g s users

Уведомление:

  1. 必须в проекте根目录Создано в (по умолчанию создано в src/). (Невозможно создать в текущей папке, иначе xxx/src/xxx будет создано автоматически. Tucao: это неразумно с Angular-cli)
  2. нужно优先Создайте новый модуль, в противном случае созданные немодульные службы, контроллеры и т. д. будут автоматически внедрены и обновлены в модуль верхнего уровня.
информация (аббревиатура: i) информация о версии для печати

Распечатайте текущую систему и используйте версию основного модуля гнезда для официальной подачи.issues

| \ | |           | |    |_  |/  ___|/  __ \| |   |_   _|
|  \| |  ___  ___ | |_     | |\ `--. | /  \/| |     | |
| . ` | / _ \/ __|| __|    | | `--. \| |    | |     | |
| |\  ||  __/\__ \| |_ /\__/ //\__/ /| \__/\| |_____| |_
\_| \_/ \___||___/ \__|\____/ \____/  \____/\_____/\___/


[System Information]
OS Version     : Windows 10
NodeJS Version : v8.11.1
NPM Version    : 5.6.0
[Nest Information]
microservices version : 5.1.0
websockets version    : 5.1.0
testing version       : 5.1.0
common version        : 5.1.0
core version          : 5.1.0

Наконец, общая функциональность иAngular-cliАналогичные, относительно простые и практичные функции. Создайте проект, сгенерируйте файлы, распечатайте информацию о версии.

встроенные функции

В настоящее времяNest.jsслужба поддержкиexpressа такжеfastify, правильноfastifyНезнакомый, эта статья выбираетexpress.

основной модуль

  • @nestjs/common предоставляет множество декораторов, служб журналов и т. д.
  • Основной модуль @nestjs/core отвечает за совместимость с базовыми фреймворками.
  • @nestjs/microservices Поддержка микросервисов
  • @nestjs/тестовый набор тестов
  • Поддержка веб-сокетов @nestjs/websockets

дополнительный модуль

  • @nestjs/typeorm еще не играл
  • @nestjs/graphql еще не играл
  • @nestjs/cqrs еще не играл
  • Аутентификация @nestjs/passport (поддерживается в версии 5, не имеет обратной совместимости)
  • @nestjs/swagger swagger UI API
  • @nestjs/mongoose модуль мангуста

Уведомление: другие промежуточные модули, если они поддерживаютexpressи то и другое можно использовать.

Построить проект

  1. Создать проектnest-cnode
nest new nest-cnode

nest_cli

который представил вашdescription, инициализированная версияversion, авторauthor, иpackage managerвыберитеnode_modulesСпособ установкиnpmилиyarn.

  1. Начало проекта
cd nest-cnode

// 启动命令

npm run start  // 预览
npm run start:dev // 开发
npm run prestart:prod  // 编译成js
npm run start:prod  // 生产

// 测试命令

npm run test  // 单元测试
npm run test:cov  // 单元测试+覆盖率生成
npm run test:e2e  // E2E测试
  1. Введение в файл проекта
документ иллюстрировать
node_modules пакет нпм
src исходный код
logs журнал
test E2E-тестирование
nodemon.json конфигурация nodemon (начало запуска npm: запуск dev)
package.json управление пакетами npm
README.md файл описания
tsconfig.json Файл конфигурации Typescript (требуется для Typescript)
tslint.json Файл проверки стиля Typescript (требуется для Typescript)
webpack.config.js Горячее обновление (запуск запуска npm: запуск hmr)
.env конфигурационный файл

код разработкиsrc, сгенерированный код находится вdist(упаковано и автоматически скомпилировано)

nest_start

Открываем браузер и заходимhttp://localhost:3000, вы должны увидеть страницу с надписьюHello WorldСлово.

j _ 2k2q0pqpjt 03o t16u

Наша последняя статья подошла к концу, смотрите наш следующий проект в действии--Nest-CNode