簡體   English   中英

結合使用Angular2 HTTP服務和緩存機制

[英]Using Angular2 HTTP Service with caching mecanism

我通過服務公開了一個HTTP GET請求,並且幾個組件正在使用此數據(國家/地區列表)。 我希望第一個組件請求實際對服務器執行HTTP GET請求並緩存結果,以便后續請求將使用緩存的數據,而不是再次調用服務器。

這是我的服務:

import {Injectable} from '@angular/core'
import {Subject} from 'rxjs/Subject';
import {Message, SelectItem} from 'primeng/primeng';
import {Http, Headers, RequestOptions} from '@angular/http';
import {environment} from '../../../environments/environment';
import {Country} from '../../domain/country';
import {Response} from "@angular/http";
import {Observable} from 'rxjs/Observable';
import {ReplaySubject} from "rxjs/Rx";
import "rxjs/add/observable/of";

@Injectable()
export class ListsService {

  private _listOfCountries:SelectItem[]=[];
  private countries:SelectItem[]=[];

  private options = new RequestOptions({headers: new Headers({'Content-Type': 'application/json'})});

  constructor(private http:Http) {
    console.log("create ListsService");
  }

  /**
   * Get all countries
   */
  getListOfCountries():Observable<SelectItem[]> {
    console.log('this._listOfCountries==');
    console.log(this._listOfCountries);
    let countries$ = this._listOfCountries.length > 0? Observable.of(this._listOfCountries): this.http
      .get(`${environment.backend_url}api/countries`, this.options)
      .map(this.mapCountries)
      .catch(this.handleError);
    return countries$;
  }

  private mapCountries(response:Response):SelectItem[] {
    let countries:Country[] = response.json();
    let selectItems:SelectItem[] = countries.map((c) => {
      return {label: c.frLabel, value: c.id}
    });
    this._listOfCountries = selectItems.map(a => Object.assign({}, a));
    console.log('this._listOfCountries==');
    console.log(this._listOfCountries);
    return selectItems;
  }

  private handleError(error:any) {
    let errorMsg = error.message || `Error during retrieving data from the API`;
    return Observable.throw(errorMsg);
  }
}

我將服務注入以下組件:

constructor(
              private listService:ListsService,
              private router: Router,
              public fb:FormBuilder) {
...
}

  ngOnInit() {

    this.listService.getListOfCountries().subscribe(countries => {
      console.log(countries);
      this.listOfCountries = countries;
    });
}

我僅在根模塊app.module.ts上聲明服務,如下所示:

...
import {ListsService} from "./shared/services/lists.service";

@NgModule({
  declarations: [
    AppComponent,
    IntroComponent,
  ],
  imports: [
    // @angular
    BrowserModule,
    FormsModule,
    ReactiveFormsModule,
    HttpModule,
    RouterModule.forRoot(routes, {useHash: true}),
    ...
    //app
    AdministrationModule,
  ],
  providers: [MessageService, ListsService],
  bootstrap: [AppComponent]
})
export class AppModule { }

我期望該服務維護_listOfCountries字段中的數據,但始終將其初始化為空數組,因此我沒有所需的行為。

任何人都可以指出我如何解決此問題,並提出解決此問題的最佳方法?

解決方案*:我修改了服務,如下所示:

@Injectable()
export class ListsService {

  private countriesSubject: Subject<SelectItem[]>;
  private countriesRequest: Observable<SelectItem[]>;

  private options = new RequestOptions({headers: new Headers({'Content-Type': 'application/json'})});

  constructor(private http:Http) {
    console.log("create ListsService");
    this.countriesSubject = new ReplaySubject<SelectItem[]>(1);
  }

  /**
   * Get all countries
   */
  getListOfCountries(refresh: boolean = false) {
    if (refresh || !this.countriesRequest) {
      this.countriesRequest =  this.http
        .get(`${environment.backend_url}api/countries`, this.options)
        .map(this.mapCountries)
        .catch(this.handleError);

      this.countriesRequest.subscribe(
        result => this.countriesSubject.next(result),
        err => this.countriesSubject.error(err)
      );
    }
    return this.countriesSubject.asObservable();
  }

  private mapCountries(response:Response):SelectItem[] {
    console.log('mapCountries');
    let countries:Country[] = response.json();
    let selectItems:SelectItem[] = countries.map((c) => {
      return {label: c.frLabel, value: c.id}
    });
    return selectItems;
  }
}

在我的組件上:

ngOnInit() {

    this.listService.getListOfCountries().take(1).subscribe(countries => {
      this.listOfCountries = countries;
    });

  }

使用ListsService組件可以預訂Observable ,然后維護自己的緩存。

@Component({...})
export class SomeComponent implements OnInit {
  private countries:SelectItem[]=[];

  constructor(private listsService: ListsService) {}

  ngOnInit() {
    this.listsService.getListOfCountries()
      .subscribe((countries: SelectItem[]) => {
        this.countries = countries;
      }
  }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM