Home > database >  Issue returning values with RXJS and Nestjs
Issue returning values with RXJS and Nestjs

Time:03-03

I'm getting some JSON from an endpoint (I'm using @nestjs/axios for this). The issue is that the response is an Observable. This complicates things when returning values. I can't seem to get async/await to work, I'm truly out of ideas...

Here's my endpoint:

async getBalance({ address, network }: WalletDto): Promise<any> {
    let nativeBalance: string

    try {
      this.httpService
        .get<{ balance: string }>(
          `https://deep-index.moralis.io/api/v2/${address}/balance?chain=${network}`,
          {
            headers: {
              Accept: 'application/json',
              'X-Api-Key': 'lol',
            },
          },
        )
        .subscribe({
          next: ({ data }) => {
            nativeBalance = utils.formatEther(data.balance)
          },
          complete: () => {
            const chain = supportedChains.find(
              ({ name }) => name.toLowerCase() === network,
            )

            return {
              chain,
              nativeBalance,
            }
          },
        })
    } catch (error) {
      // TODO handle error
    }
  }

I've messed around with .pipe() but don't understand what it does or how it works... Btw, supportedChains is a static array, not part of the fetch.

CodePudding user response:

As a super brief intro to observables: if a Promise is an object that represents exactly one eventual value, then an Observable is an object that represents a stream of any number of eventual values. Observables come with a collection of operator functions for manipulating the stream of values (that pipe function you mentioned is used to pass in any operators you want to apply).

If you just want to convert from observables to promises, then you can do so with the .toPromise property on observables. If you're using rxjs version 7 then toPromise is deprecated and instead you can use firstValueFrom or lastValueFrom.

import { firstValueFrom } 'rxjs';
//...
async getBalance({ address, network }: WalletDto): Promise<any> {
  try {
    const observable = this.httpService.get<{ balance: string }>(
      `https://deep-index.moralis.io/api/v2/${address}/balance?chain=${network}`,
      {
        headers: {
          Accept: "application/json",
          "X-Api-Key": "lol",
        },
      }
    );

    const { data } = await observable.toPromise();
    // OR in rxjs v7:
    // const { data } = await firstValueFrom(observable)

    const nativeBalance = utils.formatEther(data.balance);

    const chain = supportedChains.find(
      ({ name }) => name.toLowerCase() === network
    );

    return {
      chain,
      nativeBalance,
    };
  } catch (err) {}
}
  • Related