【问题标题】:Use value from httpClient after completion完成后使用来自 httpClient 的值
【发布时间】:2020-05-26 07:37:26
【问题描述】:

在我的 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 也完成了。

I have created an example on Stackblitz,我将所有内容都放在一个组件中。点击 div 看它不工作;)

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

【问题讨论】:

    标签: angular rxjs


    【解决方案1】:

    你需要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);
    }
    

    【讨论】:

    • 谢谢,这在示例中确实有效。我想,因为我每次都可以使用getValue() 从 BehaviorSubject 获得最后一个值,即使在完成之后,BehaviorSubject 也是正确的方法......我会在真实代码中尝试这个,但我想,这已经是答案了.
    • 和你描述的很像,shareReplay后面使用ReplaySubject,也尊重completion
    • 让我很困惑的一件事是,当它使用 ReplaySubject 时,为什么你的 getDog 函数的返回是一个简单的 Observable,而不是 ReplaySubject
    • ReplaySubject 扩展 Observable。如果你想暴露ReplaySubject的api,你可以返回它而不是Observable。据我了解,getDog 的目标是返回一个发出 Dog|booleanObservable 的流,非常适合。
    • 然而,确实如此。我明白了谢谢你,你帮了很多忙!
    猜你喜欢
    • 2020-09-27
    • 1970-01-01
    • 2019-02-04
    • 2018-12-14
    • 1970-01-01
    • 2014-11-30
    • 2013-06-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多