使用 rxjs shareReplay 防止多个 api 调用

问题描述 投票:0回答:1

我需要防止对某些路由进行多次 api 调用。 我一直听说我应该使用

shareReplay()
来防止多次 api 调用,尤其是当您在页面之间切换并返回同一页面时。我已经使用了
shareReplay()
,但是当我查看网络选项卡时,它继续发出网络请求。有任何想法吗?我在这里创建了一个 stackblitz 链接 = https://stackblitz.com/edit/angular-ivy-jadosn

这是我的

http.services
代码:

getWaterPokemon(): Observable<Filter[]> {
        return this.http.get<Filter[]>(`${this.getApi()}/type/5`, { responseType: 'json' }).pipe(
            map((clients: any) => clients.pokemon.map((client: any) => client.pokemon)),
            shareReplay()
          );
    }

这是我的

water.component
代码:

ngOnInit(): void {
    this.waterPokemon$ = this.httpService.getWaterPokemon().pipe(
      shareReplay()
    );
  }

每次进入水精灵页面时,您都会看到网络请求发生。

angular rxjs
1个回答
4
投票

这不是可观察量的工作方式。

让我解释一下(虽然很长但很有用)。

可观察量有两种类型:热或冷。

HOT observable 是一个连续发出值而不被关闭的 observable。将其视为 HTML 元素上的事件侦听器。

COLD observable 是在第一次调用后完成的 observable。把它想象成一个承诺。

因此,使用

http.get
很冷,而在可观察量上使用
shareReplay
则很热

您在这里所做的事情如下:

  • 前往水页
  • 要求服务从 API 获取数据
  • 转到另一个页面
  • 重复

使用您当前的代码,所有服务所做的就是每次调用获取函数时返回一个 HOT observable(在本例中这是无用的)。

您想要做的是存储获取的结果,这样您就不必每次都调用该服务。

这个想法是

// Service
class FetchService() {
  
  data = new BehaviorSubject<any[]>([]);
  data$ = this.data.asObservable();

  constructor(private http: HttpClient) {
    http.get('url').subscribe(res => this.data.next(res));
  }
}

// Component

class MyComponent {

  data$ = this.service.data$;

  constructor(private service: FetchService) {}
}

这样,服务在实例化时仅刷新数据一次。但是,由于该服务是单例(除非以其他方式制作),因此即使您更改页面,它的实例也会存在(组件的情况并非如此,每当您路由进/出它时,组件就会被销毁并重新创建)。

然后,该组件只需获取您服务中的记忆数据,从而防止您的应用进一步调用 API。

© www.soinside.com 2019 - 2024. All rights reserved.