【问题标题】:angular2 cache server responseangular2缓存服务器响应
【发布时间】:2017-11-21 00:01:08
【问题描述】:

我需要在我的服务中缓存服务器响应。我检查了这个问题caching results with angular2 http service,在这里我找到了两种方法 1) Observable.share() - 但正如答案中所说“他 share() 运算符仅在第一个请求时工作,当所有订阅都服务并且您创建另一个,然后它将不起作用,它将发出另一个请求” 2)使用 ReplaySubject 在使用解析器之前效果很好(它正在创建新请求)。这是我的 plunker https://plnkr.co/edit/TiODzGyQtXepojf4oPgw 你可以检查网络选项卡,当你从组件 A 导航到组件 B 时,两种方式都会创建新请求。知道如何解决这个问题吗?

我的服务

import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import * as Rx from 'rxjs';
import { Http } from '@angular/http';
import { ReplaySubject } from 'rxjs/ReplaySubject';

@Injectable()
export class ContactsService {
  goals: ReplaySubject<Array<any>> = new ReplaySubject(1);
  constructor(private http: Http) {}
  get() {
    if (!this.goals.observers.length) {
      return this.http
        .get('https://jsonplaceholder.typicode.com/posts/1');
    }

    return this.goals;
  }

  get2() {
    return this.http
        .get('https://jsonplaceholder.typicode.com/posts/1').share();
  }
}

更新

对于科目,您可以使用以下方法(由 ehrencrona 建议)

cache: ReplaySubject<Array<any>>

get() {
  if (!this.cache) {
    this.cache = new ReplaySubject(1) 
    this.http.get(url).subscribe(this.cache)
  }

  return this.cache
}

对于 observable 你可以使用我发现的这个方法

observable: Observable<any>;
get() {
    if (!this.observable) {
      this.observable = this.http.get(url).publishReplay(1).refCount();
    }

    return this.observable;
  }

请注意 .publishReplay(1).refCount() 与 .share() 不同 - 使用 .share() 它不会创建新请求

【问题讨论】:

  • 请注意,如果你在 http.get 之前放置一个 console.log,它永远不会被调用。所以!this.dataObs$.observers.length 似乎不是测试 ReplaySubject 是否有值的最佳方法。它计算订阅者的数量。

标签: angular rxjs observable


【解决方案1】:

使用 RxJS 缓存获取的值的标准模式如下:

cache: ReplaySubject<Array<any>>

get() {
  if (!this.cache) {
    this.cache = new ReplaySubject(1) 
    this.http.get(url).subscribe(this.cache)
  }

  return this.cache
}

cache 实例存储已获取的值。刚开始时,实例没有设置,这表明之前从未提取过值。当你第一次调用 get() 时,它会创建一个 ReplaySubject 并让它通过订阅 http.get 返回的原始 observable 来“回放”它从 AJAX 调用中获得的值。

那么返回值总是缓存。

请注意,此模式解决了缓存时的一个常见问题:如果第二个调用者在第一个方法完成检索之前调用该方法,它仍然只会执行一次 HTTP 调用。如果您只是缓存检索到的值而不是难以实现的可观察值。

【讨论】:

  • 看起来是正确的,你能添加一个可观察的代码吗?
  • get() { if (!this.observable) { this.observable = this.apiService.get('api_v3_secured_financialgoal_get'); } 返回 this.observable; } 这种方式创建新的请求。请检查我更新的 plunker,以便我接受您的回答
  • 主体实现了 observable 接口,因此您可以将其返回给期望 observable 的调用者。不需要使用不同类型的单独实现。
  • 是的,但是当我不打算更新这些数据时,我不想创建主题,这没有任何意义,不是吗?这就是为什么我为 observables 创建了不同的解决方案
  • 数据需要存储在某个地方。 ReplaySubject 是用于存储和“重放”可观察序列的类。所以在这里使用它是有意义的。其他解决方案当然是可能的,但我认为这个解决方案没有任何缺点。
猜你喜欢
  • 1970-01-01
  • 2011-10-09
  • 1970-01-01
  • 2012-11-27
  • 2017-05-30
  • 2020-07-03
  • 2019-09-26
  • 2016-12-30
  • 2022-01-06
相关资源
最近更新 更多