1

I'm new to Rxjs(^6.5.3). I'm using it to fetch data from api for my react app. I am making two requests which one is dependent to the other. I don't know what i did wrong, but i get this error:

// console ouput
 Observable {_isScalar: false, _subscribe: f}
 Observable {_isScalar: false, _subscribe: f}
.....

An example of how the results are shown:

// users endpoint
  {
   "data": {
    "total": 130,
    "users": [ // this format is also used as the User interface for typescript type check
        {"id": 1, "name": "John Doe", "profile_url": "https://myapi.co/user/id/1"},
        {"id": 2, "name": "Johny Doe", "profile_url": "https://myapi.co/user/id/2"}, ...
     ]
  }
 }


// user details endpoint
  {
   "data": {
    "info":{"name": "John Doe", "age": 50, "gender": "male", "status": "active", ...}
    }
 }

Here's my code that deals with fetching data from the api

 // User class
class User{
.....
   private function getAllUsers(): Observable<User[]> {
     return from(fetch(api.getUsers()).then(res => res.json()).then(res => res.data.users))
   }

   private function getUserDetails(url: string): Observable<User> {
     return from(fetch(api.getUserDetails(url)).then(res => res.json()).then(res => res.data.info))
   }

   public function getUsers(): Observable<User[]> {

    return this.getAllUsers()
      .map(users => users.map(user => user.profile_url))
      .flatMap(profiles => {
        // console.log('flatmap: ', profiles.map(profiles => this.getUserDetails(profile)))
        return r.map(x => 
          this.getUserDetails(profile)
          );
      })
      .map(users => users);
   }
}

// index page
import ...
....

 const userClass = new User();

 userClass.getUsers()
 .subscribe(users => {
 console.log('users: ', users);
 })

I found a similar issue Observable dependent on another observable

Update 1: replaced the the returned Observable type to Observable<User> or Observable<User[]>

1 Answers1

0

I think there are a few issues here. I recommend replacing the type of Observable<any> with the type the observable is actually returning which will really help you find errors. It helps me a lot when chaining together observables. Also take(1) was my friend when they weren't completing (but I only needed the first result).

That being said, this post has some good discussion on mapping.

flatMap/mergeMap - creates an Observable immediately for any source item, all previous Observables are kept alive

concatMap - waits for the previous Observable to complete before creating the next one

switchMap - for any source item, completes the previous Observable and immediately creates the next one

exhaustMap - source items are ignored while the previous Observable is not completed

You want to wait for the outer observable - getAllUsers - to complete before starting the inner observable - getUserDetails - right? You are likely looking for concatMap or switchMap instead of flatmap.

Community
  • 1
  • 1
Diesel
  • 5,099
  • 7
  • 43
  • 81
  • So i changed the type of returned observable in both my code and my post. Next thing i get is this type-checking error: `Type 'Observable>' is not assignable to type 'Observable'. Type 'Observable' is missing the following properties from type 'User[]': length, pop, push, join, and 18 more.ts(2322)`. When i comment out the inner observable, the error disappears. – Stephane Mensah Dec 01 '19 at 07:15
  • I found a solution that works for me: [flatten nested observables](https://stackoverflow.com/a/40448489/12461438). But this solution waits for all observables to finish(takes time, aprox 5mins for 500+ results) before printing the results. – Stephane Mensah Dec 01 '19 at 08:08