【问题标题】:angular 2 observable resubscribe to reuse dataangular 2 observable 重新订阅以重用数据
【发布时间】:2016-04-21 02:22:32
【问题描述】:

我正在尝试重用缓存的数据。如果没有缓存数据,则使用 http 获取数据。如果有缓存数据,则使用 observable 中的缓存数据。

这里是数据服务.ts

import {Injectable} from 'angular2/core';
import {Http, Response, Headers, RequestOptions} from 'angular2/http';
import {Observable} from 'rxjs/Observable';
import {Observer} from 'rxjs/Observer';
import 'rxjs/add/operator/share';

import {Hero} from './hero';
//import {HEROES} from './mock-heroes';


@Injectable()
export class HeroService {
  private _baseUrl: string;
  private _cachedHeroes; 

  private _heroesObserver: Observer<Hero[]>;
  private _heroObserver: Observer<Hero>;
  heroes$: Observable<Hero[]>; 
  hero$:   Observable<Hero>; 
  public _dataStore: { heroes: Hero[], hero: Hero };

  constructor (private http: Http) {
        this._dataStore = { heroes: [], hero: {_id: null, name: null} };
        this.heroes$ = new Observable(observer =>  this._heroesObserver = observer).share();
        this.hero$   = new Observable(observer =>  this._heroObserver = observer).share();
        this._baseUrl = 'http://localhost:8081/api/hero/';  // URL to web api
  }

  loadHeroes() {
      if (this._dataStore.heroes.length === 0) {
        this.http.get(`${this._baseUrl}readAll`)
                 .map(response => response.json()).publishReplay(null,1).refCount()
                 .subscribe(data => {
                                     this._dataStore.heroes = data;
                                     this._heroesObserver.next(this._dataStore.heroes);
                                    }, 
                             error => console.log('Could not load heroes.')
                            );
      }
      else {
       //   Observable.of(this._dataStore.heroes)
       this.heroes$.map(data =>this._dataStore.heroes)
       .publishReplay(null,1).refCount()   
       .subscribe(data => {
                                     this._dataStore.heroes = data;
                                     this._heroesObserver.next(this._dataStore.heroes);
                                     console.log(this.heroes$);
                                    }, 
                             error => console.log('Could not load heroes.')
                            );
      //console.log(this._heroesObserver);          
      }
  }
}

http.get().map().subscribe() 始终有效。 this._heroesObserver.isUnsubscribed 总是显示为 false。

但是当有缓存数据时 this._heroesObserver.isUnsubscribed 总是显示为真。

组件从 ngOnInit() 中调用此函数

  ngOnInit() {
    this._heroService.loadHeroes();       
    this.heroes = this._heroService.heroes$;
    this.heroes.subscribe(data => {
                                    data.forEach((h, i) => {
                                        console.log(h); 
                                    });
                                  }, 
                          error => console.log('Could not get hero.')
                         );
  }

这有关系吗?我想不是。 我该怎么做才能让它发挥作用?

更新代码以添加.publishReplay(null,1).refCount()

现在refCount 递增,isUnsubscribed 始终显示为 false。但是,组件仍然无法获取数据。第一次在组件中没有缓存数据时 console.log 正确打印所有数据。但是当有缓存数据时,console.log 什么也不打印。

【问题讨论】:

    标签: angular angular2-services


    【解决方案1】:

    使用 publishReplay(1) 将您的 observable 更改为 hot observable,它会记住并重播最后一个值并将其提供给后期订阅者:

    import * as Rx from 'rxjs/Rx';
    import 'rxjs/add/operator/map';
    import 'rxjs/add/operator/publishReplay';
    
    this.heroes$ = http.get(...).map(...).publishReplay(1).refCount();
    
    this.heroes$.subscribe(...);
    

    最后重放的值本质上是缓存的值,在发出新的 http 请求时会被替换

    【讨论】:

    • 我找不到 Observable 和 Subscriber 的 connect() 方法?
    • 抱歉,我使用的是较旧的 API。它应该是 publishReplay(),并且使用 refCount() 或 connect()。使用 refCount() 的好处是,一旦所有订阅者都取消订阅,就会自动处理共享的 observable。
    • 组件仍然无法获取数据?我更新了问题以添加代码和描述。一定有一些简单的东西我错过了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-17
    • 2018-02-28
    • 1970-01-01
    • 1970-01-01
    • 2016-10-28
    相关资源
    最近更新 更多