观察者订阅不会在第一次加载到组件

时间:2016-11-06 18:58:40

标签: javascript angular rxjs

我有一个暴露asObservable的商店。视图订阅此并显示数据。因为我已将其更改为Singleton服务,所以它正在进行首次加载,当我第一次进入页面时,没有显示数据且没有触发订阅事件。在对数据执行某些操作后,会导致subject.next被调用,它会更新并且视图会更新,一切都很棒。

我确保这不是竞争条件问题,并且在调用页面构造函数时数据存储在商店中。

事件顺序如下(在调试期间确认):

  1. 从服务器
  2. 加载数据
  3. 使用正确的数据调用subject.next()
  4. 调用组件构造函数,订阅观察者
  5. 没有订阅事件触发,也没有数据填充,即使它存在于商店中。如果我然后在列表上执行某种crud操作,则所有内容都按预期级联,调用next(),并发生订阅事件。

    如何让页面在页面加载时读取数据?

      

    data.store

    protected _subject$: Subject<Array<any>>;
    this._subject$.next(newData);  // confirmed via console this happens with good data
    
    get contacts$(): Observable<any> {
      return this._subject$.asObservable();
    }
    
      

    组件 - 我已尝试将下面的块放在构造函数和ngAfterViewInit中,结果相同

    // this happens after the above data is already set
    this.contacts$.subscribe(data => {
        // this block does not execute on page load
      });
    

1 个答案:

答案 0 :(得分:5)

  

事件顺序如下(在调试期间确认):

     
      
  1. 从服务器
  2. 加载数据   
  3. 使用正确的数据调用subject.next()
  4.   
  5. 调用组件构造函数,订阅观察者
  6.   

这是因为香草Subject没有缓冲任何东西。发出消息时,如果没有人在该确切时间订阅,则消息将永远消失,没有人会收到消息。

如果您希望保留最后一条消息(适用于所有订阅者),则可以使用BehaviorSubjectReplaySubject

import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { ReplaySubject } from 'rxjs/ReplaySubject';

sub1 = new BahaviorSubject<any>(null);
sub2 = new ReplaySubject<any>(1);

从语义上讲,BehaviorSubject表示随时间变化的值,并使用初始值初始化它。它将保持最后一项始终缓冲,直到下一项推出它。

ReplaySubject的语义是缓冲发出的项目数量,最大缓冲区大小,并在订阅时将它们全部发送给订阅者。我们可以使用缓冲区大小初始化ReplaySubject。缓冲区大小为1,将使其表现得像BehaviorSubject(但我们不需要用值初始化它)。