24

I decided to use Observable instead of Http promises.

That is how my Promise service looked:

export class MovieService {

    movies: Movie[]
    movie: Movie;
    constructor(private http:Http) { }

   getMovies(): Promise<Movie[]>{

        return this.http.get('http://api.request.com')
            .toPromise()
            .then((res:Response) => res.json()['results'])

    }
    getMovie(id: number): Promise<Movie> {
        return this.getMovies()
            .then(movies => movies.find(movie => movie.id == id));

    }

}

First I fetch an array of movies, and than I find a certain movie of the array by id. However when I try to do the same with Observable, I get an error notification on find: Property 'find' does not exist on type 'Movie[]'.

Here is what I tried with the Observable service:

export class MovieService {

    movies: Movie[];
    movie: Movie;

    constructor(private http: Http) {
    }

    getMovies(): Observable<Movie[]> {

        return this.http.get('http://api.request.com)
            .map((res: Response) => res.json()['results']);
    }

    getMovie(id: number): Observable<Movie> {
        return this.getMovies()
            .subscribe(movies => movies.find(movie => movie.id == id));
    }
}

How can I achieve the same functionality in my Observable service just like in my Promise service?

Estus Flask
  • 206,104
  • 70
  • 425
  • 565
GaborH
  • 689
  • 2
  • 11
  • 24
  • 1
    *Property 'find' does not exist on type 'Movie[]* is type error, because TS configuration is wrong. It should have `lib: ['es6']` option. – Estus Flask Nov 08 '16 at 20:37
  • You are right. I changed that and it works with the find now. Thanks. – GaborH Nov 08 '16 at 20:45

1 Answers1

33

I suppose you should use map method instead of subscribe which returns Subscription object

export class MovieService {
  movies: Movie[];
  movie: Movie;

  constructor(private http: Http) {}

  getMovies(): Observable<Movie[]> {
    return this.http.get('http://api.request.com')
      .map((res: Response) => res.json()['results']);
  }

  getMovie(id: number): Observable<Movie> {
    return this.getMovies()
      .map(movies => movies.find(movie => movie.id == id));
  }
}

Plunker Example

yurzui
  • 205,937
  • 32
  • 433
  • 399
  • I also thought of that, because I have to subscribe, when I call that function from an other component. However it gives the same error with the map. – GaborH Nov 08 '16 at 20:21
  • How do you use it? – yurzui Nov 08 '16 at 20:23
  • It would be helpful if you could post the error and/or a stacktrace. – Siri0S Nov 08 '16 at 20:29
  • Basically, I tried what you posted above, and the 'find' still gives the same error. – GaborH Nov 08 '16 at 20:29
  • 2
    @Siri0S there is no stacktrace, I am just not able to call the find method on the movies. When I hover on find, it says: Property 'find' does not exist on type 'Movie[]'. – GaborH Nov 08 '16 at 20:32
  • @yurzui Thanks for the plunker. Everything works as expected. There was a Ts configuration problem as well, as you can see above in the comment section of my question. – GaborH Nov 08 '16 at 20:47
  • Why we are using `?` in `{{movie?.title}}` – lukassz Feb 24 '17 at 14:13
  • @lukassz We are using it to avoid exception `cannot read value of undefined` because we are getting data asynchronously – yurzui Feb 24 '17 at 14:18
  • How can I avoid sending an http.get request every time? Is it good practice to store the result of the http.get in a local variable of type observable. Subsequent searches can be made using the 'id' field in the local variable This local variable can then be synced periodically with the server. – codejunkie Nov 08 '17 at 09:38