在 Angular 中使用 shareReplay(1) - 仍然调用 http 请求?

Posted

技术标签:

【中文标题】在 Angular 中使用 shareReplay(1) - 仍然调用 http 请求?【英文标题】:Using shareReplay(1) in Angular - still invokes http request? 【发布时间】:2018-12-05 06:11:32 【问题描述】:

我创建了一个演示 (ng-run),其中有一个调用 Http 请求的按钮。

当按钮被点击时,我调用这个方法:

public getData()
 this._jokeService.getData().subscribe();

这反过来调用它(从服务):

 public getData() 
    return this.http.get(API_ENDPOINT).pipe(shareReplay(1))
  

问题是每次点击时 - 我仍然看到发起了一个新的 http 请求:

问题:

为什么 shareReplay 不保留响应的最后一个值? 如何让我的代码只调用一次 http 并保留该值以供将来订阅?

编辑:solution is here

【问题讨论】:

为什么不会你看到一个新的请求?你又打电话给http.get了! shareReplay 可防止返回的 observable 的其他订阅者触发新响应,但您每次都在创建一个新响应。如果您想发出单个请求,则将现有值公开给未来的订阅者使用ReplaySubject,正如我在这里展示的那样:***.com/a/41554338/3001761。然后,您可以区分触发新请求和请求现有值,加上如果您确实需要发出额外请求,所有现有订阅者都会在可用时收到新结果。 我认为我不需要创建一个中间 ReplaySubject 来保持这些值。恕我直言 - 没有它也可以完成。 是的,没有它也可以完成,只要你只想要一个值。但是您仍然需要存储和公开一个可观察对象,不要每次都创建一个新对象。 是的,这是我的愚蠢错误。我每次都创建一个新的可观察对象(发生) 我写了一个库 ngx-RxCache github.com/adriandavidbrand/ngx-rxcache 来帮助你在 Angular 中管理这样的事情。在这里阅读它medium.com/@adrianbrand/… 【参考方案1】:

如果每次调用this.http.get(API_ENDPOINT).pipe(shareReplay(1)),每次都会触发http请求。如果你想进行一次http调用并缓存数据,推荐如下。

你首先得到数据的 observable:

 ngOninit()
    this.data$ =  this._jokeService.getData().pipe(shareReplay(1));
    

现在订阅多次:

 public getData()
     this.data$.subscribe();
    

您的服务:

public getData() 
    return this.http.get(API_ENDPOINT)
  

【讨论】:

是的,我每次都创建了一个新的 observable ......那是我的错误。 Tnx。)。这是漫长的一天...... @siva636 我明白你在这里做什么,但你能告诉我你的方法比简单地在你的服务中管道 http.get 并提取数据并将其放入一个不可观察的变量中的好处服务?【参考方案2】:

在役:

getData$ = this.http.get(API_ENDPOINT).pipe(shareReplay(1));

在组件中,需要取消订阅,一次API调用可以多次订阅:

ngOninit()
   this.data$ =  this._jokeService.getData$;
   this.data$.subscribe() 

在模板中,使用:

*ngIf="data$ | async as data"

【讨论】:

以上是关于在 Angular 中使用 shareReplay(1) - 仍然调用 http 请求?的主要内容,如果未能解决你的问题,请参考以下文章

RxSwift:如何使用 shareReplay 懒惰地获取订阅

node_modules/rxjs-compat/operator/shareReplay.d.ts(2,10) 中的错误:

typescript shareReplay()

[RxJS] Reactive Programming - Sharing network requests with shareReplay()

RxSwift,分享+重试机制

RXJS sharedReplay 在重新创建 observable 时不起作用