我有一个函数getNews()
,它基本上返回了angular的http.get请求。请求的结果是Id的数组。我想迭代我得到的这个数组并运行另一个http.get请求(函数getItem(id)
),然后返回从服务器收到的单个Id的对象。
我尝试过这样使用它:
getLatest() {
return this.http.get('all_news_url')
.map(res => res.json())
// I even tried creating Observable from array and get only 5 elements
//.map(res => Observable.from(res.json()))
//.take(5)
.map((data) => this.getItem(data))
.subscribe(
data => {
console.log(data);
}
)
}
getItem(itemId: any): Observable<any> {
console.log('item id', itemId);
return this.http.get(this.generateUrl(`item/${itemId}`))
.map(res => res.json());
}
显然,这不起作用。 getItem()
函数的参数总是作为Id的整个数组传递。
感谢大家参与这个问题。
答案 0 :(得分:9)
您可能希望使用concatMap运算符而不是map。 concatMap将返回的Observable展平为源Observable,而map返回一个可观察的observable。
如果您希望getItem()中的数据与'all_news_url'中列出的顺序相同,您可以尝试类似
的内容this.http.get('all_news_url')
.concatMap(res => Observable.from(res.json()).take(5))
.concatMap((data) => this.getItem(data))
.subscribe(
data => {
console.log(data);
}
);
使用上面的代码,对getItem()的调用将是同步的,即一次只有一个请求'item / $ {itemId}',并按顺序
如果您不关心订单并想通过一次发送多个请求来加速订单,请将第二个concatMap更改为mergeMap。请注意,请求(对于item / itemId)仍然是有序的,但不能保证响应的顺序。您可以将最大并发请求作为第三参数提供给mergeMap(通过传递undefined或null忽略第二个参数)。
.concatMap(res => Observable.from(res.json()).take(5))
.mergeMap((data) => this.getItem(data), null, 3)
传递1作为mergeMap的第三个参数将等同于concatMap
答案 1 :(得分:1)
问题
解决方案 concatMap to zip itemRequests
getList(): Observable<Item> {
return this.http.get('/list').pipe(
concatMap(list => {
const itemRequests = list.map(item => this.getItem(item))
return zip(...itemRequests)
})
)
}
getItem(item: Item): Observable<Item> {
return this.http.get(`/item?item_id=${item.id}`)
}
完成!
getList().subscribe((items: Item[]) => {
console.log(items)
})