简体   繁体   中英

How to correctly subscribe to a service that is making different HTTP get requests? [Angular]

I'm trying to subscribe to a service method that loads movie data from an API. Whenever the search is performed it searches for a different movie with a new ID. How do I subscribe to this from a component?

What I have done so far:

Service:

 search(id): Observable<Movie> { return this.http.get<Movie>('https://api.themoviedb.org/3/movie/' + id + '?api_key=KeyHidden&language=en-US'); }

Component:

 export class TitleComponent implements OnInit { movie: Movie; constructor(public ms: MovieService) {} ngOnInit() { this.ms.search(this.ms.movieid).subscribe(data => this.movie = data); } }

Button performing search:

 <button type="submit" mdbBtn (click)="ms.search(ms.movieid)" id="sub"> Search </button>

Interface Movie:

 export interface Movie { title: string; }

  1. Serving the app throws an error because the id by default is undefined. How do I subscribe without getting an error.
  2. Why the search button isn't working?
  3. How do I get only the values that are defined in the interface and discard everything else?

The search button potentially works, but you are not listening to the result.

You do a subscribe in ngOnInit , but that by itself only gets the value once (with undefined id, which throws the error).

What you probably want, is to set up an observable in the service (an actual property) and upon button click you than call search and in there you push the result of the http to that observable with .next(value) . That way the component will be notified about the result.

Something along the lines:

MovieService:

private _movie$: BehaviourSubject<Movie> = new BehaviorSubject(null);
movie$ = this.movie$.asObservable();

search(id) {
  this.http.get<Movie>(...).pipe(take(1)).subscribe(data => this.movie$.next(data));
}

TitleComponent

movie: Movie;

private terminate$: Subject = new Subject();

ngOnInit() {
  this.ms.movie$.pipe(takeUntil(terminate$)).subscribe(data => this.movie = data);
}

ngOnDestroy() {
  terminate$.next();
  terminate$.complete();
}

// You don't really show where the search-id comes from or how it is set, so here I assume it is passed in from the html
onSearch(id) {
  this.ms.search(id);
}

I personally would prefer creating a clicked observabe (see Observable from <button> click event in Angular2 ) and switchMap it to the result, which you subscribe to with async pipe.

movie$ = clicked$.pipe(
  switchMap(() => this.movieServic.search(movieId)),
);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM