在.switchMap运算符中返回.empty Observable

时间:2017-10-25 23:55:19

标签: rxjs rxjs5

我想我在RxJS库中发现了一个错误,或者无法理解它的行为。看看下面的代码:

const { Observable, Subject } = Rx;

const source$ = new Subject();

const handle = v => {
  if (v === 0) {
    source$.next(1);
    return Observable.empty();
  }  
  return Observable.interval(1000).startWith(-1).take(3);
}

source$
  .do(e => console.log('source:', e))
  // .delay(1)
  // .switchMap(v => Observable.of(null).switchMap(() => handle(v)))
  .switchMap(v => handle(v))
  .subscribe(e => console.log('handle:', e))

source$.next(0); // <- initial value
<script src="https://unpkg.com/rxjs/bundles/Rx.min.js"></script>

工作方案:当我使用source$.next(1)运行时,我看到以下结果(这是正确的):

source: 1
handle: -1
handle: 0
handle: 1

场景破碎:当我使用source$.next(0)运行时,我希望看到:

source: 0
... (exactly the same output as for the previous example)

但我只看到3个值:

source: 0
source: 1
handle: -1

解决方法1:当我在评论中看到.delay(1)时,它正常工作,就像我预期的那样。我认为这是因为默认调度程序在使用延迟时使用异步调度程序同步执行。

问题 当我使用Observable.of(null)时(参见代码中的注释),它也给了我相同的(“正确的”或预期的)结果。这是为什么?它不应该和以前一样同步吗?

1 个答案:

答案 0 :(得分:4)

行为是正确的。它是来自source的同步发射,这使得它有点奇怪。

1方法中发出handle会影响一个重新进入的调用,该调用会在 {之前} startWith -1发出Observable.empty返回{1}} - 同步发送startWith值。

这意味着switchMap首先看到startWith / interval可观察,第二看empty可见。然后它切换到empty observable,影响你看到的输出。

添加delay会阻止重新进入。