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
tapoperator 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
lastValueFromto convert the RxJS Observable into aPromiseso that it can beawaited. Straightforward and easy to work withuse operators like
mergeMaporswitchMapand 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.
