Reputation: 140
I'm building a NestJS api and need to make a call to an outside API and parse the responding data. This is a healthCheck to see if another API is up and running. Here is the basic call:
@Get('healthCheck')
public async healthCheck(
@Req() req: Request,
@Res() res: Response,
)
{
const obj = this.test(req);
console.log(obj)
}
test(req) {
const testingURL = 'https://google.com';
return this.http.get(testingURL).pipe(
map((obj: AxiosResponse) => { return obj.data } ),
tap(console.log)
);
}
I've worked extensively with angular in the past and doing any sort of ".toPromise()" or "subscribe()" on the returned data causes a "Converting circular structure to JSON".
Currently the "console.log(obj)" in the first section is printing out an observable object that cannot be parsed:
Observable {
source: Observable {
source: Observable { _subscribe: [Function (anonymous)] },
operator: [Function (anonymous)]
},
operator: [Function (anonymous)]
}
Any advice or helpful hints would be helpful. Most other posts that discuss this issue say that simple mapping the response or adding a promise fixes the issue, but it does not explain further on how to parse that observable once it's been fetched.
Edit: solution posted below.
Upvotes: 2
Views: 13622
Reputation: 570
You should inject HttpService
from HttpModule
(@nestjs/axios
) and get the axios reference like this this.httpService.axiosRef.get(...)
See official documentation for more details.
Upvotes: 1
Reputation: 140
Thanks to https://stackoverflow.com/users/9576186/jay-mcdoniel for help on this and this project reference https://github.com/jmcdo29/heart-watch/blob/feat/nest-commander/src/character-reader/character-reader.api.service.ts
Here was my working solution:
@Get('healthCheck')
public async healthCheck() {
const obj = await this.getEndpoint('https://google.com');
console.log(obj);
}
private getEndpoint(url): Promise<any> {
return lastValueFrom(
this.http.get<any>(url).pipe(
map((res) => {
return res.data;
}),
),
);
}
This should parse any get (or post) endpoint, as long as parameters/auth isn't required, and return the observable parsed into a promise in nestjs using axios.
Edit: as Jay suggested, lastValueFrom used instead of depricated toPromise()
Upvotes: 2
Reputation: 70061
unless you have a reason, don't inject @Res()
to the route handler, just return your data and let Nest handle it rather than having to call res.send()
. If you need access to response headers or setting cookies, use @Res({ passthrough: true })
You can return an observable in Nest directly and Nest will handle reading the data and sending it back for you.
if you need to read a value inside the observable, you can use the tap
operator from RxJS and pipe(tap(console.log))
to read the data
EDIT 10/15/2021
Now that I've also read that you're wanting to use this data in another API call, you have two options:
use lastValueFrom
to convert the RxJS Observable into a Promise
so that it can be await
ed. Straightforward and easy to work with
use operators like mergeMap
or switchMap
and chain together your Observables, still returning a single observable in the end. RxJS is like really powerful callbacks with extra options on top, but they can also get complex so this option usually requires a bit more nuance and dedication to ensure the operators are chained correctly.
Upvotes: 0