У меня есть функция getNews()
, которая в основном возвращает запрос angular http.get. Результатом запроса является массив идентификаторов. Я хотел бы перебрать этот массив, который я получил, и запустить еще один запрос 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()
всегда передается как целый массив идентификаторов.
Спасибо всем за участие в этом вопросе.
2 ответа
Вероятно, вы захотите использовать оператор concatMap вместо map. concatMap сводит возвращаемый Observable к исходному Observable, а map возвращает наблюдаемый или наблюдаемый.
Если вы хотите, чтобы данные из 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
Проблема
- / list -> Item []
- / item? item_id = {id} -> Предмет с дополнительным содержимым
- давайте получим Item [] с дополнительными вещами
Решение concatMap для 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)
})
Похожие вопросы
Новые вопросы
javascript
По вопросам программирования на ECMAScript (JavaScript/JS) и его различных диалектах/реализациях (кроме ActionScript). Имейте в виду, что JavaScript — это НЕ то же самое, что Java! Включите все ярлыки, относящиеся к вашему вопросу; например, [node.js], [jQuery], [JSON], [ReactJS], [angular], [ember.js], [vue.js], [typescript], [svelte] и т. д.
.map(res => res.json())
. Большое тебе спасибо.