首页 > 解决方案 > 完成后使用来自 httpClient 的值

问题描述

在我的 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我猜我也可以有用途。

狗永远不会改变。因此,为了避免对静态内容的重复调用,将loadingDog-Subjects 存储在一个数组中,并且如果已经提取了 dog,则从数组中返回存储的主题。


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();
  }

因此组件可以决定是否要显示加载标志,或者(在大多数情况下)是否已满足 observable 内容。工作正常。我在许多组件中展示了同一只狗。每个订阅至少触发一次,使用狗的内容,或者如果非常快,两次,加载状态(true在我的示例中),然后是内容。

但是如果我想稍后创建一个新的并重新使用 observable,它就行不通了。原因似乎是,HttpClient 在某一时刻完成了 Observable,因此包装 BehaviorSubject 也完成了。

我在 Stackblitz 创建了一个示例,我将所有内容都放在一个组件中。单击 div 以查看它不起作用;)

我想,我对 httpClient 的包装可能做错了。或者我可能对如何“缓存”httpResults 有更大的概念误解?或者我可以并且必须避免完成主题吗?任何帮助表示赞赏!

标签: angularrxjs

解决方案


您需要shareReplay(1),然后每次有人订阅时,他们都会得到最新的已知响应。

类似的东西。

public dogs = new Map<string, Observable<Dog|boolean>>();

public getDog(name: string): Observable<Dog|boolean> {
  if (!this.dogs.has(name)) {
    this.dogs.set(dogName, this.http
      .get<Dog|boolean>(`https://dog.ceo/api/breed/${name}/images`)
      .pipe(
        map(dog => this.someProcessing(dog)),
        shareReplay(1),
      ),
    );
  }
  return this.dogs.get(name);
}

推荐阅读