Angular2服务中的状态未由ngrx / store更新

时间:2017-06-04 10:03:46

标签: ngrx

我有这个减速器:

heroStore.reducer.ts

import { Action } from '@ngrx/store';
import {Hero} from '../models/hero';
import {BehaviorSubject} from 'rxjs/BehaviorSubject';

export const UPDATE = '[hero] UPDATE';

export function heroReducer(state: { [heroId: string]: BehaviorSubject<Hero>; } = {}, action: Action):
{ [heroId: string]: BehaviorSubject<Hero>; } {
  switch (action.type) {
    case UPDATE:
      let newState;
      const hero: Hero = action.payload;
      if (state[hero.uid]) { // hero exists
        newState = state[hero.uid].next(hero);
      } else {
        const heroObservable = new BehaviorSubject<Hero>(hero);
        newState = Object.assign({}, state, {[hero.uid]: heroObservable});
      }
      console.log('New State', newState);
      return newState;

    default:
      return state;
  }
}

以及以下服务

hero.service.ts

getHero(heroId: string): BehaviorSubject<Hero> {
  let state;
  this.store.select('heroStore').subscribe(s => state = s);
  console.log('state returned in service', state);
  return state[heroId];
}

最后进行以下测试:

  it('should be able to get a hero', inject([HeroService], (service: HeroService) => {
    expect(service).toBeTruthy();

    heroReducer({}, {
      type: '[hero] UPDATE',
      payload: {
        uid: '5',
        name: 'Franz'
      }
    });

    const heroObs = service.getHero('5');
    expect(heroObs.getValue().name).toEqual('Franz');

  }));

但不知何故,州没有得到更新。它产生以下日志:

  

日志:&#39;新状态&#39;,对象{5:BehaviorSubject {_isScalar:false,   观察者:[],关闭:false,isStopped:false,hasError:false,   thrownError:null,_value:Object {uid:...,name:...}}}

     

日志:&#39;状态在服务&#39;,对象{}

中返回

因此reducer实际上返回了正确的新状态。但是当在服务中订阅时,我仍然得到一个空对象。

如果我理解正确,ngrx / store中的商店是一个rxjs BehaviorSubject,它反过来应该在订阅时返回 last 值。来自BehaviorSubject的文档:

  

观察者可以订阅主题以接收最后(或初始)值以及所有后续通知

那么状态仍然是一个空对象怎么可能呢?

1 个答案:

答案 0 :(得分:-1)

您的getHero编码不正确,我认为它会返回未分配的值。写一个更好的方法是:

getHero(heroId: string): BehaviorSubject<Hero> {
  let state = new BehaviorSubject<Hero>();
  this.store.select('heroStore').subscribe(s => state.next(s[heroId]));
  return state;
}

甚至更好:

getHero(heroId: string): Observable<Heor> {
    return this.store.select('heroStore')
        .map(heros => heros[heroId];
}

或者如果你想真正优雅,这可能会有效:

getHero(heroId: string): Observable<Heor> {
    return this.store.select('heroStore', heroId);
}