发布于 1年前

Angular4使用Rxjs5共享Http请求返回的结果数据

在使用Angular开发的单页面应用里,有时需要处理这种场景:使用http请求某个数据,数据请求成功后需要把数据更新到多个组件里。也就是说,有多个observer(观察者)对http请求数据返回的Observable订阅。

getDta() {
    return this.http.get('/dataUrl').map(res => res.json());
}
let dataObservable = getDta();

let subscriber1 = dataObservable.subscribe(...);
let subscriber2 = dataObservable .subscribe(...);

如果代码类似上面这样写,你会发现http发了两次请求。这明显和我们的设想有出入,我们是希望http请求完后共享请求的数据。

这里分为两种场景:

  1. 请求的数据是固定不变的,可以考虑把请求的数据缓存起来

请求数据后是要同时更新多个组件,下次需要重新请求再更新相应的组件

缓存共享数据

对于请求数据是固定不变的或者是在一段时间内不会发生修改,可以考虑把数据缓存起来。

示例:

import {Injectable} from '@angular/core';
import {Http, Headers} from '@angular/http';
import {Observable} from 'rxjs/Observable';
import 'rxjs/add/observable/of'; //proper way to import the 'of' operator
import 'rxjs/add/operator/share';
import 'rxjs/add/operator/map';
import {Data} from './data';

@Injectable()
export class DataService {
  private url:string = 'https://cors-test.appspot.com/test';

  private data: Data;
  private observable: Observable<any>;

  constructor(private http:Http) {}

  getData() {
    if(this.data) {
      //数据已存在,返回数据的Observable
      return Observable.of(this.data); 
    } else if(this.observable) {
      //数据还没有返回,正在请求中,返回该请求的observable
      return this.observable;
    } else {
      //还没有发起请求,发起http请求。
      this.observable = this.http.get(this.url)
      .map(response =>  {
        //数据返回后,此次的observable不再需要,下次访问返回data的Observable
        this.observable = null;
        if(response.status == 400) {
          return "FAILURE";
        } else if(response.status == 200) {
          this.data = new Data(response.json());
          return this.data;
        }
      })
      .share();//使用share(),允许多个订阅获取结果
      return this.observable;
    }
  }
}

多组件共享每次请求的数据

对于每次请求的数据可能会被修改,那么就不适合缓存数据了。

Rxjs 5.4.0新增了shareReplay()函数,可以使用它来共享http ajax请求的数据

示例

getDta() {
    return this.http.get('/dataUrl').map(res => res.json()).shareReplay();
}
let dataObservable = getDta();
©2020 edoou.com   京ICP备16001874号-3