【问题标题】:Calling another observable with the response of another in Angular 4在 Angular 4 中调用另一个 observable 并响应另一个 observable
【发布时间】:2018-08-04 02:13:30
【问题描述】:

我正在使用HttpClient 编写一个显示电影放映时间的Angular 4 应用程序。数据所在的 JSON 文件有 2 个:showtimes.jsonmovies.json

// showtimes.json    
[{
"id": "2030c64ce72b4e4605cb01f2ba405b7d",
"name": "Arclight", // need to display this information
"showtimes": {
  "b4c2c326a4d335da654d4fd944bf88d0": [ // need to use this id
      "11:30 pm", "2:45 pm", "8:35 pm", "4:15 pm", "10:30 pm"
  ]
 } 
}]

// movies.json
[{
"b4c2c326a4d335da654d4fd944bf88d0": { // to retrieve the title, rating, and poster
  "title": "Fifty Shades Darker", // needs to be displayed
  "rating": "R", // needs to be displayed
  "poster": "https://dl.dropboxusercontent.com/s/dt6wgt92cu9wqcr/fifty_shades_darker.jpg" // needs to be displayed
}
}]

我有可以检索剧院的titlename 的服务。但现在我必须使用showtimes 对象中的值来显示正确的标题名称。如您所见,b4c2c326a4d335da654d4fd944bf88d0 是电影标题的 id,可以从 movies.json 文件中检索到。

到目前为止,这是我的组件

ngOnInit() {
  this._moviesDataService.getShowtimes()
  .subscribe(res => this.results = res)
}

这是我的服务。

getShowtimes (): Observable<ShowTimes> {
  return this._http.get<ShowTimes>(this._showtimesURL)
}

我的问题是如何使用电影的 id 检索电影的 title?这需要两个链式 Observable 吗?我需要遍历电影数组和.filter 吗?

我已经包含了一个我正在尝试构建的示例

【问题讨论】:

  • 是的,你需要组合 observables。查看例如forkJoin 和各种 map 方法。

标签: angular typescript rxjs observable angular2-observables


【解决方案1】:

通常,当你有一个 Observable 并且你需要从 .它并返回一个不同的 Observable,你可以使用switchMap:

ngOnInit() {
    this._moviesDataService.getShowtimes()
        .switchMap(res => { 
            const id = Object.keys(res[0].showtimes)[0]; // assuming you have one element in your array and you want the first id from showtimes
            return this.getMovies(id); // assuming, you have a separate method that returns the movies
        })
        .subscribe(res => this.results = res)
}

更新

由于您需要 Observable 的结果,而且您​​还需要第一个的结果来请求第二个的结果,所以这里有一个想法,您可以如何做到这一点:

ngOnInit() {
    this._moviesDataService.getShowtimes()
        .switchMap(res => { 
            const showtimes = res[0].showtimes;
            const id = Object.keys(showtimes)[0];

            return Observable.zip(
                this.getMovies(id),
                Observable.of(showtimes[id])
            );
        })
        .subscribe(([movies, showtimes]) => {
            this.results.movies = movies; // or assign it to some other property
            this.results.showtimes = showtimes; // and use in the template
        }

【讨论】:

  • 不,forkJoin 接受多个请求并将响应作为数组返回,您不能根据从另一个接收到的数据发送一个请求,您需要一个 switchMap(或 mergeMap)跨度>
  • 我实际上需要显示来自getShowtimes() 的数据,然后传入showtimes 对象以从getMovies(). 检索标题当我遍历this.results 时,只有来自@987654328 的数据@ 有没有。有没有办法将数据从第一次调用发送到前端,并使用switchMap() 执行另一个 Observable?
  • 你能用你想要的输出更新你的帖子吗(你想让this.results等于什么)?很难理解你到底需要做什么。
  • 太棒了!得到了我需要的两个回复!
  • 太棒了!乐于助人!
【解决方案2】:

我认为因为您需要检索所有电影的标题,所以您必须将第一个请求响应中的 ID 数组链接成一系列对电影标题的请求。像这样:(假设你有一个像 getMovieTitle 这样的方法,它根据电影的 id 获取电影的数据并返回一个 observable)

this._moviesDataService.getShowtimes()
        .switchMap(res => { 
            let resArray: any[] = res.map(
                    item=>this._moviesDataService.getMovieTitle(
                        Object.keys(item.showtimes)[0]
            ))
            return Observable.merge(...resArray);
        })
        .subscribe(res => /*you will get a new res for each movie title here*/)

Observable.merge 是做什么的,是Turn multiple observables into a single observable.,所以您将在一次订阅中获得所有结果。

注意: 不要忘记将所有这些分配给 subscription 并在组件的 ngOnDestroy 处取消订阅(以防止内存泄漏)

【讨论】:

  • 我实际上需要显示来自getShowtimes() 的数据,然后传入showtimes 对象以从getMovies(). 检索标题当我遍历this.results 时,只有来自@987654332 的数据@ 有没有。有没有办法将数据从第一次调用发送到前端,并使用switchMap() 执行另一个 Observable?
猜你喜欢
  • 2019-01-07
  • 1970-01-01
  • 2021-02-05
  • 1970-01-01
  • 1970-01-01
  • 2021-05-12
  • 2019-01-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多