В моем проекте Angular (9) я получаю некоторые значения с помощью HttpClient
из Rest-API. Я подписываюсь на него в разных местах (в основном с трубкой async
, не напрямую, но все равно). Чтобы сделать его многоадресным, я "оборачиваю" результат HTTP-сервиса в BahaviorSubject
:
const loadingDog = new BehaviorSubject<Dog|boolean>(true);
const subscription = this.getDogFromHttpClient(dogName)
.pipe(map((dog: Dog|boolean) => this.someProecessing(dog)))
.subscribe(loadingDog);
return loadingDog;
Я мог бы также использовать share
Я думаю.
Собаки никогда изменение. Итак, чтобы избежать дублирования вызовов к содержимому stati c, сохраните loadingDog
-Subjects в массиве и, если собака уже извлечена, верните сохраненный Subject из массива.
public dogs: BehaviorSubject<Dog|boolean>[] = [];
public getDog(name: string): BehaviorSubject<Dog|boolean> {
if (isDefined(this.dogs[dogName])) {
return this.dogs[dogName];
}
const loadingDog = new BehaviorSubject<Dog|boolean>(true);
const subscription = this.http
.get<Dog>(`https://dog.ceo/api/breed/${dogName}/images`)
.pipe(map((dog: Dog|boolean) => this.someProcessing(dog)))
.subscribe(loadingDog);
this.dogs[dogName] = loadingDog;
return loadingDog;
}
И в другом компоненты, которые я использую так:
ngOnInit(): void {
this.useMeInTemplate$ = dogService.getDog('akita').asObservable();
}
Таким образом, компонент может решить, хочет ли он отображать знак загрузки или (в большинстве случаев), если наблюдаемое уже выполнено, контент. Работает отлично. Я показываю одну и ту же собаку во многих отношениях. Каждая подписка запускается по крайней мере один раз, с содержимым Dog или, если очень быстро, дважды, с состоянием загрузки (true
в моем примере), а затем с содержимым.
Но если я хочу создать новый позже и повторно использовать наблюдаемое, это не сработает. Причина, по-видимому, в том, что HttpClient завершает Observable в какой-то момент, и, таким образом, завершается и упаковка BehaviorSubject.
Я создал пример на Stackblitz , где я поместил все в один компонент. Нажмите на div, чтобы увидеть, что он не работает;)
Думаю, моя упаковка httpClient могла быть сделана неправильно. Или у меня может быть более серьезное концептуальное заблуждение о том, как «кэшировать» httpResults? Или можно и нужно избегать завершения темы? Любая помощь приветствуется!