NestJS Как использовать асинхронное промежуточное ПО? - PullRequest
1 голос
/ 20 июня 2019

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

Мой код

Асинхронное промежуточное ПО (page-loader.middleware)

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

@Injectable()

export class PageLoader implements NestMiddleware {

  async use(req: any, res: any, next: () => void) {
    try {
      req.body.html = await req.body.fetcher.fetch();
    } catch (error) {
      throw new Error(error);
    } finally {
      next();
    }
  }

}

Контроллер (create-article.controller)

import { Controller, Post, Body } from '@nestjs/common';
import { SaveArticleService } from './save-article.service';
import { CreateArticleDto } from './create-article.dto';

@Controller()

export class CreateArticleController {

  constructor(private readonly saveArticleService: SaveArticleService) {}

  @Post('/create')
  async create(@Body() createArticleDto: CreateArticleDto) {
    return this.saveArticleService.save(createArticleDto);
  }

}

Модуль (create-article.module)

import { Module, NestModule, MiddlewareConsumer, RequestMethod } from '@nestjs/common';
import { CreateArticleController } from './create-article.controller';
import { SaveArticleService } from './save-article.service';

// Another (sync) middleware
import { ExtensionExtractor } from './extension-extractor.middleware'; 

// The async middleware
import { PageLoader } from './page-loader.middleware';

@Module({
  controllers: [CreateArticleController],
  providers: [SaveArticleService],
})

export class CreateArticleModule implements NestModule {
  configure(consumer: MiddlewareConsumer) {
    consumer
    .apply(ExtensionExtractor, PageLoader)
    .forRoutes({ path: 'create', method: RequestMethod.POST});
  }
}

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

Что я пробовал

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

Эти ответы github не актуальны, так как API NestJS кардинально изменился.

Заранее спасибо за помощь!

1 Ответ

1 голос
/ 21 июня 2019

Вы можете абсолютно использовать асинхронное промежуточное ПО с Nest; Однако существует проблема с использованием стратегии .forRoutes({path: 'path', method: method});.

Я настроил быстрого потребителя промежуточного программного обеспечения, чтобы показать, как это работает, без использования RequestMethod.GET.

UserModule (с включенным промежуточным программным обеспечением)

import { MiddlewareConsumer, Module, NestModule, RequestMethod } from '@nestjs/common';
import { UserController } from './user.controller';
import { UserService } from './user.service';

function asyncTimeout(milliseconds: number): Promise<string> {
  return new Promise((resolve, reject) => {
    setTimeout(() => resolve('DONE'), milliseconds);
  });
}

@Module({
  controllers: [UserController],
  providers: [UserService],
  exports: [UserService]
})
export class UserModule implements NestModule {
  configure(consumer: MiddlewareConsumer) {
    consumer
      .apply((req, res, next) => {
        console.log('Using forRoutes(path)');
        console.log('syncronous middleware');
        next();
      },
        (async (req, res, next) => {
          console.log('Using forRoutes(path)');
          const start = Date.now();
          const done = await asyncTimeout(5000);
          console.log(done);
          console.log('Time taken:' + (Date.now() - start));
          next();
        })
      )
      .forRoutes('/')
      .apply((req, res, next) => {
        console.log('Using forRoutes({path, method})');
        console.log('syncronous middleware');
        next();
      },
        (async (req, res, next) => {
          console.log('Using forRoutes({path, method})');
          const start = Date.now();
          const done = await asyncTimeout(5000);
          console.log(done);
          console.log('Time taken:' + (Date.now() - start));
          next();
        })
      )
      .forRoutes({path: '/', method: RequestMethod.GET});
  }
}


UserController (Snippet)

import { Controller, Get } from '@nestjs/common';
import { UserSerivce } from './user.service';

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

  @Get('/')
  testFunction() {
    return {greeting: 'hello'};
  }
}

выход

[2019-06-20 22:40:48.191] [INFO] | Listening at http://localhost:3333/api
Using forRoutes(path)
syncronous middleware
Using forRoutes(path)
DONE
Time taken:5002
[2019-06-20 22:40:57.346] [INFO] | [Nest] 30511 [Morgan] GET /api/user 200 5014.234 ms - 20

Я использовал одни и те же функции промежуточного программного обеспечения в обеих установках, но вы можете видеть, что асинхронное промежуточное программное обеспечение реагирует, как и ожидалось, при использовании .forRoutes(path), но не при использовании .forRoutes({path, method}) (простите за мой пользовательский регистратор).

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

...