По сути, есть 2 варианта:
Это вариант, который вы используете, где вы используете forkJoin()
для объединения всех наблюдаемых в массив
- PROS: вы знаете, что все ваши данные будут загружены в вас
subscribe()
- CONS: вам придется ждать каждый HTTP-запрос к fini sh до того, как
forkJoin
выдаст значение - Примечание: вы можете реализовать хорошую вспомогательную функцию, такую как рекомендуется @Prince
Вы можете использовать mergeMap()
для своих идентификаторов и реагировать всякий раз, когда один наблюдаемых завершает
- PROS: вам не нужно ждать каждого HTTP-запроса для завершения. Вы можете реагировать , когда они завершат . Кроме того, вы можете легче обрабатывать ошибки (поэтому, если один запрос не будет выполнен, вы все равно сможете продолжить работу с другими запросами).
- CONS: Вы должны обрабатывать свои значения в
.subscribe()
немного по-другому
В конце дня Вам нужно будет решить, какой подход лучше для вас. В вашей реализации нет ничего плохого. Я заметил, что вы сохраняете ваш loadedCharacter
как объект, поэтому, честно говоря, вариант 2 может подойти для вашего варианта использования
Пример кода для Вариант 2 . Посмотрите это stackblitz для небольшой демонстрации:
import { Component } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable, from, Subject } from 'rxjs';
import { mergeMap, takeUntil } from 'rxjs/operators';
@Component({
selector: 'app-root',
templateUrl: 'app/app.component.html'
})
export class AppComponent {
private endSubs$ = new Subject();
loadedCharacter: {};
constructor(private http: HttpClient) {}
ngOnInit() {
/* ids of all the characters you want to load*/
const characterIds = [1, 2];
/* this will emit each id as a value */
from(characterIds).pipe(
/* merge each id to an Observable of the http get request */
mergeMap(id => this.http.get(`https://swapi.co/api/people/${id}`)),
/* cancel any pending requests when the component unloads.
this will avoid any RxJS memory leaks */
takeUntil(this.endSubs$)
).subscribe(
character => {
/* note that you will only receive 1 character at a time */
console.log('received character', character);
this.loadedCharacter[character.id] = character; // or whatever you want to do
},
err => console.log('Error loading a character', err),
() => console.log('All character requests have finished')
);
}
/* clean up our subscriptions when the component destroys */
ngOnDestory() {
this.endSubs$.next();
this.endSubs$.complete();
}
}
РЕДАКТИРОВАТЬ: Я добавил некоторый код очистки Rx JS, чтобы избежать утечек памяти из mergeMap
, Любые запросы, ожидающие завершения загрузки этого компонента, будут отменены. Вот пример ответа SO , объясняющего наблюдаемую очистку, и здесь есть соответствующая статья Rx JS о том, где разместить takeUntil()
.