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

时间:2018-11-08 10:14:02

标签: javascript node.js asynchronous nestjs long-running-processes

我需要执行以下操作:

  1. 授权通话
  2. 验证
  3. 返回202接受状态
  4. 继续处理请求
  5. 使用先前已接受并已处理的请求的结果来调用外部API。

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

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

此外,也许还有另一种更好的方法?没有拦截器,只是将所有流逻辑放在控制器中?还有其他选择吗?

2 个答案:

答案 0 :(得分:2)

我希望您有一个服务(异步)执行外部API调用,并返回PromiseObservable

@Injectable()
export class ExternalApiService {
  constructor(private readonly httpService: HttpService) {}

  makeApiCall(data): Observable<AxiosResponse<any>> {
    return this.httpService.post('https://external.api', data);
  }
}

我还假设有一个PreprocesserService进行异步调用(例如,从数据库中获取用户信息)。

控制器

@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或返回Promise / Observable明确告诉控制器方法时,控制器方法才会执行。

在此示例中,我们要在发送响应之前等待this.preprocessService.preprocess(myDataDto)的结果。我们通过使用await(该方法必须声明为async)来实现。

我们想向外部API发出请求,但我们不需要响应结果。因为我们这里没有使用await,所以它将进行http调用并立即执行下一行(return语句),而无需等待结果。

答案 1 :(得分:1)

如果您的服务返回了一个Promise,您可以执行以下操作,则在处理继续进行时,API将返回202。当然,“ beginProcessing”完成后,所有使用“ then”的处理都会发生。

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