Home > Software design >  NestJS API calls and reading response data within the API
NestJS API calls and reading response data within the API

Time:10-16

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:

  1. 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 })

  2. You can return an observable in Nest directly and Nest will handle reading the data and sending it back for you.

  3. 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:

  1. use lastValueFrom to convert the RxJS Observable into a Promise so that it can be awaited. Straightforward and easy to work with

  2. 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.

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.

  • Related