当前位置: 首页 > 知识库问答 >
问题:

Angular 2缓存可观察超文本传输协议结果数据[重复]

呼延聪
2023-03-14

我有一个通过HTTP服务获取数据并返回可观察对象的服务。

在第一次调用之后,我希望在服务内部缓存结果,一旦一个新组件尝试获取数据,它将从缓存的结果中获取数据。

有没有简单的解决方案?

共有3个答案

巫研
2023-03-14

您可以构建简单的类 可缓存

declare type GetDataHandler<T> = () => Observable<T>;

export class Cacheable<T> {

    protected data: T;
    protected subjectData: Subject<T>;
    protected observableData: Observable<T>;
    public getHandler: GetDataHandler<T>;

    constructor() {
      this.subjectData = new ReplaySubject(1);
      this.observableData = this.subjectData.asObservable();
    }

    public getData(): Observable<T> {
      if (!this.getHandler) {
        throw new Error("getHandler is not defined");
      }
      if (!this.data) {
        this.getHandler().map((r: T) => {
          this.data = r;
          return r;
        }).subscribe(
          result => this.subjectData.next(result),
          err => this.subjectData.error(err)
        );
      }
      return this.observableData;
    }

    public resetCache(): void {
      this.data = null;
    }

    public refresh(): void {
      this.resetCache();
      this.getData();
    }

}

用法

声明可缓存

list: Cacheable<string> = new Cacheable<string>();

和处理程序:

this.list.getHandler = () => {
// get data from server
return this.http.get(url)
.map((r: Response) => r.json() as string[]);
}

来自组件的调用:

//gets data from server
List.getData().subscribe(…)

更多细节和代码示例如下:http://devinstance.net/articles/20171021/rxjs-cacheable

邓越泽
2023-03-14

我认为您不应该在构造函数中或angular生命周期中的任何时候执行fetch()。正如您所说,ngOnInit在角度服务中不起作用。

相反,我们希望利用 rxjs 通过流无缝地传递缓存值 - 而调用方不必了解缓存值与非缓存值的任何信息。

如果一个组件需要一个数据,它就订阅它,不管它是否被缓存。为什么要获取()一个你不确定会被使用的数据呢?

缓存应该在更高的层次上实现,我认为这种实现是一个好的开始:http://www.syntaxsuccess.com/viewarticle/caching-with-rxjs-observables-in-angular-2.0

getFriends(){
    if(!this._friends){
      this._friends = this._http.get('./components/rxjs-caching/friends.json')
                                   .map((res:Response) => res.json().friends)
                                   .publishReplay(1)
                                   .refCount();
    }
    return this._friends;
}

我不确定这是不是最好的方法,但是它更容易维护,因为它只有一个责任。只有当一个组件订阅数据时,数据才会被缓存,不管是什么/谁/哪个组件需要数据并且是第一个需要它的。

艾令雪
2023-03-14

如果您倾向于将observables作为一种共享数据的方式,您可以采用以下方法:

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';

import { Observable, ReplaySubject } from 'rxjs';

import { SomeModel } from 'path/to/it';

@Injectable({
  providedIn: 'root'
})
export class CachedService {
 
  private dataSubject = new ReplaySubject<SomeModel>(1);
  
  data$: Observable<SomeModel> = this.dataSubject.asObservable();

  constructor(private http: HttpClient) { }

  fetch() {
    this.http.get<SomeModel>(...).subscribe(res => this.dataSubject.next(res));
  }
}

这将在调用 fetch 方法时进行 HTTP 调用,并且 service.data$ 的任何订阅者都将从 ReplaySubject 获得响应。当它重播早期值时,在 HTTP 调用解析后加入的任何订阅者仍将获得以前的响应。

如果您想触发更新,您可以调用service.fetch()来启动新的HTTP调用,一旦新响应到达,所有订阅者都将被更新。

您的组件看起来会像这样:

@Component({ ... })
export class SomeComponent implements OnDestroy, OnInit {

  private subscription?: Subscription;

  constructor(private service: CachedService) { }

  ngOnInit() {
    this.service.fetch();
    this.subscription = this.service.data$.subscribe(...);
  }

  ngOnDestroy() {
    if (this.subscription) {
      this.subscription.unsubscribe();
    }
  }
}

我最近为我的同事写了一篇关于这种方法的博客文章:http://blog.jonrshar.pe/2017/Apr/09/async-angular-data.html

 类似资料:
  • 我试图禁用我的AngularJS应用程序中的缓存,但它无法使用以下代码: 当我使用

  • 我只是有一个关于服务中http请求的结构和处理响应的问题。我正在使用Angular2。alpha46 Typescript(刚刚开始测试-我喜欢它…Ps…。感谢所有一直致力于它并通过github作出贡献的人) 因此,采取以下措施: 登录表单。组成部分ts 从这个组件中,我导入了我的userService,它将容纳我的超文本传输协议请求,以登录用户。 使用者服务ts 我想做的是能够处理http请求之

  • 我所做的: 我正在使用vertx rx超文本传输协议客户端来执行大量的HTTP请求。在这种情况下,我调用“方法A”,它返回一个ID列表。要接收所有ID,我需要多次调用方法A以获取下一批结果。(每次我指定一个不同的页码我想接收) 为了提高性能并尽可能并行地进行调用,我创建了一个(RxJava)可观察项目列表,每个项目代表单个页面请求的结果。当我完成创建此列表时,我调用Obserable.zip运算符

  • 我有一个由Python构建的API服务器。我需要一组客户端/计算机通过发出http post请求将数据发送到API服务器。 这里的数据实际上是html内容。(注意:我没有将合法数据转换为HTML/XML格式,数据本身就是我从web上收集的HTML),通常每页约200KB。我正试图通过使用串行/串行和压缩来尽可能减轻网络负载。 我正在考虑通过网络发送原始超文本标记语言。有没有类似序列化html对象的

  • 我以前问过这个问题,但没有得到答案。我可以使用下面的方法:“get”让它工作,所以这没关系,但这次我需要使用post。在另一个项目中(使用react、redux、php、webpack、xampp),同样的问题再次出现,我正在努力解决它。这就是: register.php index.js 当我做了以上的一切是好的,数据是日志作为'做某事'。但是,当我尝试使用axios({方法:'POST'})并

  • 我正在使用GWT和Spring controller来管理http流量。有些请求可能需要很长时间,但我希望在超过给定时间时终止请求。 我如何配置超时Spring。我也使用Apache Tomcat 7.0。我试图在tomcat上inrease最大线程,但有一段时间tomcat工作缓慢,因为请求线程不会死。