代码之家  ›  专栏  ›  技术社区  ›  Forseti

如何返回202 Accepted,然后在Nest.js中继续处理请求

  •  0
  • Forseti  · 技术社区  · 7 年前

    我需要一个控制器动作:

    1. 验证它
    2. 返回接受状态
    3. 使用以前接受的和现在处理的请求的结果调用外部API。

    前两点很简单,我用 AuthGuard 然后 class-validator . 但我不知道如何返回HTTP响应,然后继续处理。

    由于请求由一系列(可能是长时间运行的)任务组成,我考虑使用拦截器,拦截器使用RxJS来观察任务的状态,并在任务完成时调用外部PI。但是,我没有使用RxJS或拦截器的经验(不是这种方式),所以我真的不知道如何让拦截器的进程保持运行,而是立即将控制传递给控制器的操作。

    另外,也许还有另一个更好的方法?没有拦截器,只是把所有的流逻辑放在控制器里?还有别的选择吗?

    2 回复  |  直到 7 年前
        1
  •  8
  •   Kim Kern    7 年前

    Promise Observable :

    @Injectable()
    export class ExternalApiService {
      constructor(private readonly httpService: HttpService) {}
    
      makeApiCall(data): Observable<AxiosResponse<any>> {
        return this.httpService.post('https://external.api', data);
      }
    }
    

    我还假设有一个进行异步调用的预处理服务(例如从数据库获取用户信息)。

    控制器

    @Post()
    @UseGuards(AuthGuard('jwt'))
    @HttpCode(HttpStatus.ACCEPTED)
    async post(@Body(new ValidationPipe()) myDataDto: MyDataDto) {
      // The preprocessing might throw an exception, so we need to wait for the result
      const preprocessedData = await this.preprocessService.preprocess(myDataDto);
                               ^^^^^
      // We do not need the result to respond to the request, so no await
      this.externalApiService.makeApiCall(preprocessedData);
      return 'Your data is being processed.';
    }
    

    当您进行异步调用时,控制器方法的执行只会在您通过使用 async/await 或返回 承诺 可观察的 .

    在本例中,我们希望等待 this.preprocessService.preprocess(myDataDto) 在我们发送回复之前。我们通过使用 await (方法必须声明为 async ).

    等待

        2
  •  4
  •   Rich Duncan    7 年前

    如果您的服务返回一个承诺,您可以执行如下操作,那么在处理过程继续时,API将返回202。当然,“then”的任何处理都是在“beginProcessing”完成之后进行的。

    @Post()
    @HttpCode(HttpStatus.ACCEPTED)
    beginProcessing(@Req() request, @Body() data: Data): void {
        this.service.process(data).then(...);
    }