Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TypeScript - wait for an observable/promise to finish, and return observable

I am quite new to TypeScript & RxJS, and I am trying to return an Observable after another Observable is finished:

public myObservable = () : Observable<boolean> => {     console.log('retrieving the token in DB');     return Observable.create(observer => {         setTimeout(() => {             observer.next(true);             observer.complete();         }, 5000);     }); }  public makeRequest = (): Observable<any> => {     return this.myObservable().subscribe(         function (x) {             console.log('I have the token, now I can make the HTTP call');              return this.http.get('http://jsonplaceholder.typicode.com/posts/1')                 .map( (responseData) => {                     return responseData.json();                 })                 .map((item:any) => {                     return {                         id: item.id,                         userId: item.userId,                         title: item.title,                         body: item.body                     };                 });          },         function (err) {             console.error('Error: ' + err);         },         function () {             console.log('Completed');         });  } 

I received this error: "Returned expression type subscription is not assignable to type Observable<any>".

I totally understand the error here (an Observable is like a stream, and a subscription is the fact of "observing" that stream), but I don't see how to "wait" for an Observable (or a promise) to finish to return a new Observable. How can I do that?

like image 736
Geoffrey D Avatar asked May 18 '16 15:05

Geoffrey D


2 Answers

The problem is that we convert observable into different type... with .subscribe - while we should not (it does not return observable)

public makeRequest = (): Observable<any> => {     return this.myObservable().subscribe(       ... // this is wrong, we cannot return .subscribe           // because it consumes observable and returns ISusbcriber     ); } 

When we have an observable... we should just take its result and use .map to convert it to something else

FlatMap operator

transform the items emitted by an Observable into Observables, then flatten the emissions from those into a single Observable

public makeRequest = (): Observable<any> => {     return this.myObservable()        .flatmap((x) => return this.http               .get('http://jsonplaceholder.typicode.com/posts/1')               .map( (responseData) => {                     return responseData.json();               })               ... 

Check all the details here

TAKING ADVANTAGE OF OBSERVABLES IN ANGULAR 2

like image 62
Radim Köhler Avatar answered Oct 02 '22 00:10

Radim Köhler


While flatMap() may work, since you are not passing in a parameter that is used[see param (x)], the best operator for you to use in this scenario is forkJoin().

Please see this example: https://stackoverflow.com/a/38049268/1742393

   Observable.forkJoin(     this.http.get('/app/books.json').map((res:Response) => res.json()),     this.http.get('/app/movies.json').map((res:Response) => res.json()) ).subscribe(   data => {     this.books = data[0]     this.movies = data[1]   },   err => console.error(err) ); 
like image 20
rbj325 Avatar answered Oct 02 '22 01:10

rbj325