3

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.

jcobo1
  • 1,065
  • 1
  • 18
  • 34
  • 1
    see this https://stackoverflow.com/questions/63462672/benefits-of-observable-with-http-in-angular – Moshezauros Apr 11 '21 at 18:59
  • Yes works on both ways but I'd appreciate if someone with more experience could explain me where's the difference and what option is more appropriate – jcobo1 Apr 11 '21 at 19:00

1 Answers1

4

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:

  • a http.get observable to retrieve movies
  • the user typing in an input field, possibly piped through a debounce
  • combining it with a http.post to query alternative movies
  • combineLatest all of those and possibly pipe through a debounce or distinctUntilChanged to do UI updates at the right time
  • etc.

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.

Jeroen
  • 60,696
  • 40
  • 206
  • 339
  • Thanks Jeroen this is the kind of explanation I was looking for. So, following the example I posted maybe the best option is to return an observable from my service but maybe on the component use the pipe operator to transform it to an promise? Because the only think I do when subscribing is store the response value on a variable. – jcobo1 Apr 11 '21 at 19:56
  • Aye. Although I'm not sure why your component would want to convert it to a Promise? The component can just `subscribe` to the result and use it, or you can use the `async` pipe (which handles subscribing/unsubscribing for you) to directly view the movies in the component. – Jeroen Apr 12 '21 at 09:29