最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to return 202 Accepted and then continue processing the request in Nest.js - Stack Overflow

programmeradmin0浏览0评论

I need a controller action that:

  1. Authorizes the call
  2. Validates it
  3. Returns the 202 Accepted status
  4. Continues processing the request
  5. Makes a call to external API with the results of previously accepted and now processed request.

First two points are easy, I use AuthGuard then class-validator. But I don't know how to return the HTTP response then continue with processing.

As the request consists of an array of (possibly long-running) tasks I thought of using interceptor that uses RxJS to observes the status of tasks and calls external PI upon their completion. However, I have no experience with using RxJS or interceptors (not this way) so I'd really don't know how to leave interceptor's process running but immediately pass control to controller's action.

Also, perhaps there is another, better way? No interceptor but just put all the flow logic in the controller? Some other option?

I need a controller action that:

  1. Authorizes the call
  2. Validates it
  3. Returns the 202 Accepted status
  4. Continues processing the request
  5. Makes a call to external API with the results of previously accepted and now processed request.

First two points are easy, I use AuthGuard then class-validator. But I don't know how to return the HTTP response then continue with processing.

As the request consists of an array of (possibly long-running) tasks I thought of using interceptor that uses RxJS to observes the status of tasks and calls external PI upon their completion. However, I have no experience with using RxJS or interceptors (not this way) so I'd really don't know how to leave interceptor's process running but immediately pass control to controller's action.

Also, perhaps there is another, better way? No interceptor but just put all the flow logic in the controller? Some other option?

Share Improve this question edited Nov 9, 2018 at 21:03 Kim Kern 60.4k20 gold badges216 silver badges212 bronze badges asked Nov 8, 2018 at 10:14 ForsetiForseti 2,9456 gold badges25 silver badges34 bronze badges
Add a comment  | 

2 Answers 2

Reset to default 12

I expect you have a service that does the external API call (asynchronously) and returns either a Promise or an Observable:

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

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

I also assume that there is a PreprocesserService that makes asynchronous calls (for example getting user information from a database).

Controller

@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.';
}

When you make asynchronous calls, the execution of your controller method will only wait if you explicitly tell it to by either using async/await or returning a Promise / an Observable.

In this example, we want to wait for the result of the this.preprocessService.preprocess(myDataDto) before we send the response. We do that by using await (the method must be declared as async).

We want to make the request to the external API but we do not need the result for our response. Because we are not the using await here it will make the http call and immediately execute the next line (the return statement) without waiting for the result.

If your service returns a promise you could do something like the following, the API will return 202 while the processing continues. Of course any processing with the 'then' is happening after 'beginProcessing' is complete.

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

评论列表(0)

  1. 暂无评论