I need a controller action that:
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?
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(...);
}
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).
@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 you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With