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.
CodePudding user response:
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 callres.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 andpipe(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 aPromise
so that it can beawait
ed. Straightforward and easy to work withuse operators like
mergeMap
orswitchMap
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.
CodePudding user response:
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 this.http
.get<any>(url)
.pipe(
map((res) => {
return res.data;
}),
)
.toPromise();
}
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.