为什么RxJS主题上的next()方法停止通知前端

时间:2016-09-02 18:54:45

标签: angular typescript rxjs

我偶然发现了这个Plunkr http://plnkr.co/edit/yMBoVkxohwhPig5COgkU?p=preview

它显示了一个可观察的数据服务。我的问题所在的部分显示:

export class TodoService {
  private _todos$: Subject<Todo[]>; 
  private baseUrl: string;
  private dataStore: {
    todos: Todo[]
  };

  constructor(private http: Http) {
    this.baseUrl  = 'http://56e05c3213da80110013eba3.mockapi.io/api';
    this.dataStore = { todos: [] };
    this._todos$ = <Subject<Todo[]>>new Subject();
  }

  get todos$() {
    return this._todos$.asObservable();
  }

  loadAll() {
    this.http.get(`${this.baseUrl}/todos`).map(response => response.json()).subscribe(data => {
      this.dataStore.todos = data;
      this._todos$.next(this.dataStore.todos);
    }, error => console.log('Could not load todos.'));
  }

上面的代码运行正常。但是,当我使用不进行http调用的代码替换loadAll时:

  loadAll() {
    this.dataStore.todos = [{ 'id': '1', 'createdOn': 1472831416, 'value': 'value 1' }, { 'id': '2', 'createdOn': 1472831360, 'value': 'value 2' }, { 'id': '4', 'createdOn': 1472831771, 'value': 'value 4' }, { 'id': '5', 'createdOn': 1472831716, 'value': 'value 5' }, { 'id': '6', 'createdOn': 1472831658, 'value': 'value 6' }];
    this._todos$.next(this.dataStore.todos);
  }

它停止通知前端,如此Plunkr所示:http://plnkr.co/edit/ObiWt2cm6sGSgW2Hf5ya?p=preview

有人可以解释为什么会这样,以及如何让它发挥作用?

1 个答案:

答案 0 :(得分:2)

Subject期望将一个项目传递给它,而不是项目数组。你在做什么类似于:

let subject = new Subject<{ message: string }>();
subject.onNext([{ message: 'test one' }, { message: 'test two' }]);

这是错误,应该在编译时生成错误。

正如我所提到的,onNext期望一个项的泛型类型,而不是项目数组。所以这样的事情是正确的:

let subject = new Subject<{ message: string }>();
subject.onNext({ message: 'test one' });

如果要从数组中的项创建observable,您有几个选项,第一个是遍历数组并为数组中的每个项调用onNext,如所以:

let subject = new Subject<{ message: string }>();
let items = [{ message: 'test one' }, { message: 'test two'}];
items.forEach(item => subject.onNext(item));

另一种方法是从数组中创建一个observable:

let subject = new Subject<{ message: string }>();
let items = [{ message: 'test one' }, { message: 'test two'}];

let itemsObservable = Observable.from(items);

在此示例中,itemObservable将替换您的:

get todos$() {
    return this._todos$.asObservable();
}

并成为:

get todos$() {
    return this.itemObservable;
}

希望这能解决一些问题。解决方案中的基本问题基本上是您误解了Subject的工作原理。