Herbie Vine
Herbie Vine

Reputation: 2025

Issue returning values with RXJS and Nestjs

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.

Upvotes: 0

Views: 1349

Answers (1)

Nicholas Tower
Nicholas Tower

Reputation: 85012

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) {}
}

Upvotes: 3

Related Questions