Сводка
Как правильно использовать Angular 7 для загрузки списка, а затем выполнить итерацию по этому списку, делая вызовы http для заполнения дополнительных данных?
Подробности
Я использую Angular 7 на сервере Node.JS.
Мне нужно отобразить список элементов.Я могу получить основные детали, скажем, название и изображение предмета, очень быстро.Тем не менее, некоторые детали требуют некоторого времени для вычисления на бэкэнде - скажем, сколько раз оно было куплено и состояние, которое приобрело большую часть предмета.
Идея состоит в том, чтобы иметьзагрузите базовую информацию в список, а затем начните сверху и начните заполнять сложные данные.
Итак, у меня есть 2 API.
- Возвращает список из 200+элементы с их названием, ценой и изображением (ответы в ~ 500 мс).
- При наличии списка идентификаторов, вернуть комплексную информацию для элемента (~ 250 мс-2000 мс).
Вот псевдокод того, что я сделал:
public ngOnInit() {
this.service.getList().subscribe(list => {
this.items = list;
list.forEach(i => pendingIds.push(i.id));
this.loadDetails();
});
}
public pendingIds = [];
public loadDetails() {
ids = this.pendingIds.popAFew();
this.service.getDetails(ids).subscribe(info => {
this.items[id].properties = info.properties;
if (pendingIds.length) {
this.loadDetails();
}
});
}
Приведенный выше код "работает", но страница дрожит / не очень отзывчива, пока все данные не заканчивают загружаться.
Если я уберу вызов loadDetails (), то страница загружается быстро и мгновенно реагирует.
Я уверен, что проблема связана с вложением наблюдаемых объектов, которое выполняется потенциально сотни раз.Тем не менее, я не смог найти в Интернете пример, который делает то, что я пытаюсь сделать.
Я играл с асинхронным каналом и 'rxjs / observable / from', но я не нашел секретсоус.
У кого-нибудь есть примеры того, как лениво загружать информацию в список?
Редактировать
Я пытался использовать flatMap, см.следующий, но все еще нервный:
public pendingIds = [];
public loadDetails() {
let obs: Observable<any>;
this.pendingIds.forEach(id => {
if (!obs) {
obs = this.service.getDetails(id).pipe(tap((info) => this.loadDetails(info)));
} else {
obs = obs.pipe(
flatMap(() => this.service.getDetails(id)),
tap((infp) => this.loadDetails(info))
);
}
});
obs.subscribe(() => {{);
}
Редактировать 2
3-й способ загрузки - все еще нервный.
let activeRequests = 0;
Observable.create((observer) => {
const interval = setInterval(() => {
if (activeRequests < 2) {
if (this.pendinIds.length > 0) {
observer.next(this.pendingIds.shift());
} else {
clearInterval(interval)
}
}
}, 25);
return () => clearInterval(interval);
})
.pipe(flatMap(id => { activeRequests++; return this.service.getDetails(id); })
.subscribe(info => { --activeRequests; this.loadDetais(info})
Любойидеи?