angularpromiseobservableangular-promiserxjs-observables

Angular api call: Observable vs Promise


I have this service that calls to an API to get a bunch of movie descriptions and returns an Observable:

getNowPlayingMovies$(page: number, country?: string): Observable<NowPlaying> {
    console.log(`${this.baseUrl}${this.now_playing}?${this.key}&region=${country || 'US'}&page=${page}`);
    return this.http.get<NowPlaying>(
      `${this.baseUrl}${this.now_playing}?${this.key}&region=${country || 'US'}&page=${page}`
    );
  }

On the component that uses this function above I call it changing every time the page value so I can offer to the user pagination on the component view.

And this is the component that calls the service:

getNowPlayingMovies(): void {
    this.nowPlayingService.getNowPlayingMovies$(this.page).subscribe((data) => {
      this.nowPlaying.push(
        ...data.results.filter((result) => result.backdrop_path)
      );
      if(!this.last_page){
        this.last_page = data.total_pages
        this.page++;
      } else if(this.page <= data.total_pages) {
        this.page++;
      }
      console.log(data);
      console.log(this.nowPlaying);
    });
  }

I've read that on Angular you should always try to work using Observable rather than Promises but on scenarios like this I don't see any advantage of subscribing to the api call response.

It would be correct to transform the Observable in the service to a Promise like this?

getNowPlayingMovies$(page: number, country?: string): Promise<NowPlaying> {
    console.log(`${this.baseUrl}${this.now_playing}?${this.key}&region=${country || 'US'}&page=${page}`);
    return this.http.get<NowPlaying>(
      `${this.baseUrl}${this.now_playing}?${this.key}&region=${country || 'US'}&page=${page}`
    ).toPromise();
  }

I'm learning Angular and I'm working this to add it to my portfolio so I want to learn to do it the right way and the best way possible.


Solution

  • It would not be incorrect, as in: it will work.

    You do loose some features in translation to a Promise, but the most important one is usually irrelevant: in my experience the methods on http do not return observables that emit multiple values. Do note that the observable API does leave this possibility open. You can dig in to the relevant source to learn more.

    One reason why many resources probably still suggest you should work with observables is that many other features in Angular are or can/should be built with observables. Think about working with reactive forms, combining multiple http requests, user events, etc. If you stick to using observables for all of them, RxJs offers you powerful (yet arguably complex and/or complicated) ways to combine them. Consider for example:

    Building all those interactions when you convert http calls to Promise<T> right away will be a bunch of extra work, and might feel non-idiomatic even.

    Having said all that, I have on occasion done what you described and "simplified" a service, making it return promises instead of observables. But in most cases it might seem a good idea at first, and will make things harder later down the line.