1

I'm trying to understand how to extract data from an object of type Observable, after not some research I fall mainly on two solutions. subscribe (which does not work in my case or which I use badly), or map which does not exist any more. I specify I use nest.

here my goal is to be able to directly return the variable this.followers filled with the data of the answer

Here is my code.

import { HttpService } from '@nestjs/axios';
import { Injectable } from '@nestjs/common';
import { GithubFollower } from './../../../../shared/github.models'

@Injectable()
export class GithubService {
  private followers: GithubFollower[]

  constructor(private httpService: HttpService) {}

  getFollowers(id: string): GithubFollower[] {
    this.httpService.get<GithubFollower[]>(`https://api.github.com/users/${id}/followers`)
      .subscribe(data => {
        this.followers = data.data // this.followers = my data
        console.log(this.followers); // print my data
      });
    console.log("here", this.followers); // print "here undefined"
    return this.followers; // this.followers = []
  }
}

How do I extract data from an Observable?

Rayder-_-
  • 199
  • 1
  • 2
  • 13
  • 1
    Why does subscribing not work in your case? As far as I know, the map operator still exists. – Exitare Nov 20 '21 at 00:41
  • 1
    Does this answer your question? [How do I return the response from an Observable/http/async call in angular?](https://stackoverflow.com/questions/43055706/how-do-i-return-the-response-from-an-observable-http-async-call-in-angular) – R. Richards Nov 20 '21 at 00:48
  • this answers it partly, but the problem is that I would like to wait for the return of my request and then be able to return the value of this one – Rayder-_- Nov 20 '21 at 01:01
  • because I use nest and data is of type ```AxiosResponse``` – Rayder-_- Nov 20 '21 at 01:04
  • Yes, but since I use nestjs the ```httpService``` object comes from the ```@nestjs/axios``` lib which as its name indicates contains a wrap of the axios lib so the variable type is ```AxiosResponse``` – Rayder-_- Nov 20 '21 at 01:06
  • Making a [Stackblitz](https://stackblitz.com/) makes it easier to help you hands on. I'll gladly take a closer look if you do. You shouldn't usually subscribe though, but rather pipe and map your observable like Exitare already pointed out. – H3AR7B3A7 Nov 20 '21 at 01:17

2 Answers2

1

although .toPromise is deprecated in RxJs 8, you can use it in rxjs versions 7 and below. So try this out:

async getFollowers(id: string): GithubFollower[] {
    const githubData = await this.httpService.get<GithubFollower[]>(`https://api.github.com/users/${id}/followers`).toPromise()
    this.followers = githubData.data
    return this.followers; // this.followers now returns the followers instead of undefined
  }
kzoeps
  • 396
  • 5
  • 15
0

following my question of yesterday evening, I found two solutions. The first one is to use the pipe function (even if I don't understand well what it does, I would be happy to have an explanation in the comments of this post) which gives us this:

  getFollowers(id: string): Observable<DashBoardResponse> {
    return this.httpService
      .get<GithubFollower[]>(`https://api.github.com/users/${id}/followers`)
      .pipe(
        map(res => {
          const response: DashBoardResponse = {
            code: res.data !== [] ? 200 : 400,
            message: res.data !== [] ? 'success' : 'Possible bad id',
            response: res.data
          }
          return response;
        })
      )
  }

then nest is able to extract the response from the controller before sending it back to the client.

The second solution that I could have is the one of @KZoeps a little bit modified, because on the current version of nest it is not possible to use an async/await function without returning a Promise. Here is the code: here my goal is to be able to directly return the variable this.followers filled with the data of the answer

  async getFollowers(id: string): Promise<DashBoardResponse> {
    this.followers = await (await this.httpService.get<GithubFollower[]>(`https://api.github.com/users/${id}/followers`).toPromise()).data
    return new Promise((resolve, reject: (reason?: DashBoardResponse) => void) => {
      if (this.followers !== []) {
        resolve({
          code: 200,
          message: 'success',
          response: this.followers
        });
      } else {
        reject({
          code: 400,
          message: 'Possible bad id',
          response: []
        })
      }
    })
  }

Thank you in any case for your help.

Rayder-_-
  • 199
  • 1
  • 2
  • 13