NestJS 如何使用异步中间件?
NestJS How to consume async middleware?
我使用 NestJS 框架,并希望将多个中间件应用到我应用程序中的路由。每个中间件都是一个 class 实现 NestMiddleware 接口。这些中间件之一是异步的,并且在调用路由处理程序之前不会被使用。有没有办法在处理路由之前解决这个中间件的承诺?
我的代码
异步中间件(页面-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();
}
}
}
控制器(创建-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);
}
}
模块(创建-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 issue 答案不相关,因为 NestJS API 发生了巨大变化。
在此先感谢您的帮助!
你绝对可以在 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});
}
}
用户控制器(片段)
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 一起提出来解决,但您的设置否则有效。如果您选择打开一个,请随意使用我在这里的任何代码来为该问题设置一个示例 repo。
我使用 NestJS 框架,并希望将多个中间件应用到我应用程序中的路由。每个中间件都是一个 class 实现 NestMiddleware 接口。这些中间件之一是异步的,并且在调用路由处理程序之前不会被使用。有没有办法在处理路由之前解决这个中间件的承诺?
我的代码
异步中间件(页面-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();
}
}
}
控制器(创建-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);
}
}
模块(创建-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 issue 答案不相关,因为 NestJS API 发生了巨大变化。
在此先感谢您的帮助!
你绝对可以在 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});
}
}
用户控制器(片段)
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 一起提出来解决,但您的设置否则有效。如果您选择打开一个,请随意使用我在这里的任何代码来为该问题设置一个示例 repo。