使用 Angular 2 中的 Observables 获取数据一次 [英] Fetch data once with Observables in Angular 2

查看:12
本文介绍了使用 Angular 2 中的 Observables 获取数据一次的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个服务,它从我的许多 Angular 2 组件中多次使用.它从 Web API 获取客户数据并返回一个 Observable:

I have a service, what is used several times from a lot of my Angular 2 components. It fetches customer data from a Web API and returns an Observable:

getCustomers() {
   return this.http
        .get(this.baseURI + this.url)
        .map((r: Response) => {
            let a = r.json() as Customer[];                       
            return a;                         
        });               
}    

我将此服务注入到我的根组件中,并且在每个想要访问客户的组件中都注入了我订阅的 Observable:

I inject this service in my root component, and in every component that wants to access the customers I just subscribe to that Observable:

this.customerService.getCustomers().subscribe(v => this.items = v);

然而,订阅我的 Observable 的每个组件都会导致 HTTP 请求的另一次执行.但是只获取一次数据就足够了.如果我尝试 share(),它并不能解决我的问题:

However, every component who subscribes to my Observable causes another execution of the HTTP-request. But to fetch the data only once is enough. If I try share(), it does not solve my problem:

getCustomers() {
   return this.http
        .get(this.baseURI + this.url)
        .map((r: Response) => {
            let a = r.json() as Customer[];                       
            return a;                         
        }).share();               
}   

还是一样的问题.我必须使用哪些运算符才能只获取一次数据?

Still the same issue. Any proposals which operators I have to use to only fetch data once?

推荐答案

1) 您可以简单地将下载的数据保存在您的服务中:

1) You can simply save downloaded data in your service:

export class CustomersService {
  protected _customers: Array<Customer>;

  constructor(public http: Http) {}

  public getCustomers(): Observable<Array<Customer>> {
    return new Observable(observer => {
      if (this._customers) {
        observer.next(this._customers);
        return observer.complete();
      }
      this.http
        .get(this.baseURI + this.url)
        .map((r: Response) => (r.json() as Array<Customer>))
        .subscribe((customers: Array<Customer>) => {
          this._customers = customers;
          observer.next(this.customers);
          observer.complete();
        });
    });
  }
}

2) 采用 refresh 参数的更短方法:

2) Shorter approach taking refresh parameter:

export class CustomersService {
  protected _customers: Array<Customer>;

  constructor(public http: Http) {}

  public getCustomers(refresh?: boolean): Observable<Array<Customer>> {
    if (!refresh && this._customers) {
      return Observable.of(this._customers);
    }
    return this.http
            .get(this.baseURI + this.url)
            .map((c: Response) => (c.json() as Array<Customer>))
            .do((customers: Array<Customer>) => {
                this._customers = customers;
            });
    });
  }
}

3) 利用ReplaySubject:

export class CustomersService {
  protected _customers$: ReplaySubject<Array<Customer>> = new ReplaySubject(1);
  protected _customersInitialized: boolean;

  constructor(public http: Http) {}

  public getCustomers(refresh?: boolean): Observable<Array<Customer>> {
    if (refresh || !this._customersInitialized) {
      this._customersInitialized = true;
      this.http
        .get(this.baseURI + this.url)
        .map((c: Response) => (c.json() as Array<Customer>))
        .subscribe((customers: Array<Customer>) => {
          this._customers$.next(customers);
        });
    }
    return this._customers$.asObservable().skip(+refresh).distinctUntilChanged();
  }
}

然后:

this.customersService.getCustomers()
    .subscribe(customers => this.customers = customers);

您还可以通过这种方式公开 SomeService 中始终最新的 customers 字段以用于只读目的(例如在模板中显示):

You can also expose the always up-to-date customers field from SomeService for read only purposes (like displaying in the templates) this way:

public get customers(): ReadonlyArray<Customer> {
  return this._customers;
}

这篇关于使用 Angular 2 中的 Observables 获取数据一次的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆