Fetch data once with Observables in Angular 2

前端 未结 4 1959
旧时难觅i
旧时难觅i 2020-12-29 12:32

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:

getCus         


        
4条回答
  •  天命终不由人
    2020-12-29 12:41

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

    export class CustomersService {
      protected _customers: Array;
    
      constructor(public http: Http) {}
    
      public getCustomers(): Observable> {
        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))
            .subscribe((customers: Array) => {
              this._customers = customers;
              observer.next(this.customers);
              observer.complete();
            });
        });
      }
    }
    

    2) Shorter approach taking refresh parameter:

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

    3) Taking advantage of ReplaySubject:

    export class CustomersService {
      protected _customers$: ReplaySubject> = new ReplaySubject(1);
      protected _customersInitialized: boolean;
    
      constructor(public http: Http) {}
    
      public getCustomers(refresh?: boolean): Observable> {
        if (refresh || !this._customersInitialized) {
          this._customersInitialized = true;
          this.http
            .get(this.baseURI + this.url)
            .map((c: Response) => (c.json() as Array))
            .subscribe((customers: Array) => {
              this._customers$.next(customers);
            });
        }
        return this._customers$.asObservable().skip(+refresh).distinctUntilChanged();
      }
    }
    

    And then:

    this.customersService.getCustomers()
        .subscribe(customers => this.customers = 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 {
      return this._customers;
    }
    

提交回复
热议问题