每个Observable的值排放

时间:2018-06-15 14:16:51

标签: javascript typescript rxjs reactive-programming reactivex

假设我们有以下代码(Stackblitz):

  public counter: number = 0; // Some arbitrary global state

  public ngOnInit(): void {
    const subj: Subject<number> = new Subject<number>();

    const obs: Observable<number> = subj.asObservable().pipe(
      tap((): void => {
        ++this.counter;
      }));

    // this.counter increments for each subscription.
    // But supposed to increment once per obs new value emition.
    obs.subscribe();
    obs.subscribe();
    obs.subscribe();

    subj.next(1);

    // Now this.counter === 3
  }

结果是this.counter在执行上述操作后等于3,每次订阅都会增加一次。

但是,我们如何以反应方式每Observable的新价值排放增加一次呢?

我知道我们应该避免在Reactive流程之外的状态,但在现实世界的应用程序中仍然需要时间。

2 个答案:

答案 0 :(得分:2)

您看到号码3的原因略有不同。当您使用of(1)时,它会发出一个next通知,然后发出complete通知。每次拨打obs.subscribe()时都会这样做。

因此,如果您想查看1,您需要创建一个中间主题,您在其中进行所有订阅,然后此中间主题订阅源Observable(最简单地使用publish()运算符创建主题你):

const obs: ConnectableObservable<number> = of(1).pipe(
  tap((): void => {
    ++this.counter;
  }),
  publish(),
) as ConnectableObservable<number>;

obs.subscribe();
obs.subscribe();
obs.subscribe();

obs.connect();

您的最新演示:https://stackblitz.com/edit/rxjs-update-global-state-ejdkie?file=app/app.component.ts

请注意,of(1)无论如何都会发出complete通知,这意味着publish()内的主题也会完整。这可能(或可能不是)对你来说是一个问题,但它实际上取决于你的用例。

修改:这是更新的演示,其中来源为主题:https://stackblitz.com/edit/rxjs-update-global-state-bws36m?file=app/app.component.ts

答案 1 :(得分:0)

请尝试一次这样的事情。我无法在任何地方运行它。如果它出错,请告诉我

  public counter: number = 0;
  public items: any = [];

  public ngOnInit(): void {
    const obs: Observable<number> = of(1).pipe(
      tap((value): void => {
        if(! Array.prototype.includes(value)) {
           this.items.push(value);
            ++this.counter;
         }
      }));

    // this.counter increments for each subscription.
    // How to make it increment once per obs new value emission.
    obs.subscribe(1);
    obs.subscribe(2);
    obs.subscribe(1);

    // Now this.counter === 3
  }