Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting errors trying to get observable from "observable's chain"

Well. I've got some async code in my Angular component, that works just fine. Looks like this (briefly):

export class SomeComponent {

    user: User;
    /* ... */
    email: string;
    /* ... */

    private someMethod(): void {
      /* some code here */
      this.userService1.getUsers().subscribe(users => {
        users.forEach(user => {
          if (user.email && user.email === this.email) {
             this.userService2.getUser(user.id).subscribe(foundUser => {
               let someFields;
               if (foundUser) {
                 someFields = (({ field1, field2 }) => ({ field1, field2 }))(foundUser); 
               }
               this.user = {...user, ...someFields};
             });
           }
         });
      });
      /*some code here */              
    }
 }

I skip some types and name variables a bit awkward (but simple) cause it's not the point. Code works. But I wanna encapsulate process of user's constructing (from 2 services) cause I'll need it in different components. I tried, but...

constructUser(email): Observable<IUser> {
  let finalUser: IUser;

  return this.userService1.getUsers().merge(users => {
    return users.filter(user => {
      if (user.email && user.email === email) {
        return this.userService2.getUser(user.id).map(foundUser => {
          let someFields;
          if (foundUser) {
            someFields = (({ field1, field2 }) => ({ field1, field2 }))(foundUser); 
          }
          finalUser =  {...user, ...someFields};

          return Observable.of(finalUser);
        });
      }
    });
  });
}

My WebStorm shows no error. But in console I'm getting this.userService1.getUsers(...).merge is not a function.

I've tried merge, concat, flatMap, whatever - but still no success. The only difference was errors that I've got. I do not have much experience with rxjs, so I'm stuck. Any help or tips will be greatly appreciated.

UPD.
Solved, but for 7 days (while bounty is active) anyone still welcome with more concise and functional solutions :)

like image 335
impregnable fiend Avatar asked Jun 08 '18 20:06

impregnable fiend


1 Answers

I think something like this is what you want:

RxJs 5:

import 'switchMap' from 'rxjs/add/operator/switchMap';
import 'map' from 'rxjs/add/operator/map';


this.userService1.getUsers()
    .map(users => users.find(userInList => userInList.email === "SomeEmail")) //Map the observable with users to a single user
    .switchMap(user => this.userService2.getUser(user.id)) //Map the observable by an other observable
    .subscribe(...doSomething with the result)

RxJs 6:

import {map, switchMap} from 'rxjs/operators';

this.userService1.getUsers().pipe(
    map(users => users.find(userInList => userInList.email === "SomeEmail")), //Map the observable with users to a single user
    switchMap(user => this.userService2.getUser(user.id)) //Map the observable by an other observable
).subscribe(...doSomething with the result)
like image 133
Robin Dijkhof Avatar answered Nov 05 '22 09:11

Robin Dijkhof