加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

Angular 2使用observable的功能缓存http请求

发布时间:2020-12-17 18:10:23 所属栏目:安全 来源:网络整理
导读:我发现了许多缓存反应式可观察量的方法,更具体地说,是http请求的结果.但是,由于以下原因,我对提议的解决方案并不完全满意: 1.此答案https://stackoverflow.com/a/36417240/1063354使用私有字段存储第一个请求的结果,并在所有后续调用中重用它. 代码: priva
我发现了许多缓存反应式可观察量的方法,更具体地说,是http请求的结果.但是,由于以下原因,我对提议的解决方案并不完全满意:

1.此答案https://stackoverflow.com/a/36417240/1063354使用私有字段存储第一个请求的结果,并在所有后续调用中重用它.

代码:

private data: Data;    
getData() {
    if(this.data) {
        return Observable.of(this.data);
    } else {
        ...
    }
}

可悲的是,可观察力的力量完全被忽略了 – 你手动完成所有的东西.事实上,如果我对将结果分配给局部变量/字段感到满意,我就不会寻找合适的解决方案.
我认为一个不好的做法的另一个重要的事情是服务不应该有一个状态 – 即应该没有包含从一个调用到另一个调用的数据的私有字段.清除缓存相当容易 – 只需将this.data设置为null,即可重新执行请求.

2.这个答案https://stackoverflow.com/a/36413003/1063354建议使用ReplaySubject:

private dataObs$= new ReplaySubject(1);

    constructor(private http: Http) { }

    getData(forceRefresh?: boolean) {
        // If the Subject was NOT subscribed before OR if forceRefresh is requested 
        if (!this.dataObs$.observers.length || forceRefresh) {
            this.http.get('http://jsonplaceholder.typicode.com/posts/2').subscribe(
                data => this.dataObs$.next(data),error => {
                    this.dataObs$.error(error);
                    // Recreate the Observable as after Error we cannot emit data anymore
                    this.dataObs$= new ReplaySubject(1);
                }
            );
        }

        return this.dataObs$;
    }

看起来非常棒(再次 – 清除缓存没有问题)但我无法映射此调用的结果,即

service.getData().map(data => anotherService.processData(data))

这是因为底层观察者没有调用其完整方法.我很确定很多反应方法也不适用于此.要实际获取数据,我必须订阅此observable,但我不想这样做:我想通过解析器获取我的一个组件的缓存数据,该解析器应该返回一个Observable(或Promise),而不是订阅:

路线

{
    path: 'some-path',component: SomeComponent,resolve: {
      defaultData: DefaultDataResolver
    }
}

解析器

...
resolve(route: ActivatedRouteSnapshot,state: RouterStateSnapshot): Observable<Data> {
    return this.service.getData();
}

永远不会激活组件,因为它的依赖性永远不会被解析.

3.在这里https://stackoverflow.com/a/36296015/1063354我找到了一个使用publishLast().refCount()的提议.

代码:

getCustomer() {
    return this.http.get('/someUrl')
        .map(res => res.json()).publishLast().refCount();
}

这满足了我对缓存和解析的要求但是我还没有找到一个干净整洁的解决方案来清除缓存.

我错过了什么吗?任何人都可以想出一种更好的方法来缓存反应性可观察量能够映射其结果,以及一旦它不再相关就刷新缓存数据吗?

解决方法

这个简单的类缓存结果,因此您可以多次订阅.value并只发出1个请求.您还可以使用.reload()发出新请求并发布数据.

您可以像以下一样使用它:

let res = new RestResource(() => this.http.get('inline.bundleo.js'));

res.status.subscribe((loading)=>{
    console.log('STATUS=',loading);
});

res.value.subscribe((value) => {
  console.log('VALUE=',value);
});

和来源:

export class RestResource {

  static readonly LOADING: string = 'RestResource_Loading';
  static readonly ERROR: string = 'RestResource_Error';
  static readonly IDLE: string = 'RestResource_Idle';

  public value: Observable<any>;
  public status: Observable<string>;
  private loadStatus: Observer<any>;

  private reloader: Observable<any>;
  private reloadTrigger: Observer<any>;

  constructor(requestObservableFn: () => Observable<any>) {
    this.status = Observable.create((o) => {
      this.loadStatus = o;
    });

    this.reloader = Observable.create((o: Observer<any>) => {
      this.reloadTrigger = o;
    });

    this.value = this.reloader.startWith(null).switchMap(() => {
      if (this.loadStatus) {
        this.loadStatus.next(RestResource.LOADING);
      }
      return requestObservableFn()
        .map((res) => {
          if (this.loadStatus) {
            this.loadStatus.next(RestResource.IDLE);
          }
          return res;
        }).catch((err)=>{
          if (this.loadStatus) {
            this.loadStatus.next(RestResource.ERROR);
          }
          return Observable.of(null);
        });
    }).publishReplay(1).refCount();
  }

  reload() {
    this.reloadTrigger.next(null);
  }

}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读