【问题标题】:Returning .empty Observable inside .switchMap operator在 .switchMap 运算符中返回 .empty Observable
【发布时间】:2017-10-25 23:55:19
【问题描述】:

我想我在 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
&lt;script src="https://unpkg.com/rxjs/bundles/Rx.min.js"&gt;&lt;/script&gt;

工作场景:当我使用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: 当我在 cmets 中看到 .delay(1) 时 - 它工作正常,正如我所预期的那样。我认为这是因为默认调度程序在同一滴答声中同步执行,而在使用延迟时使用异步调度程序。

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

【问题讨论】:

标签: rxjs rxjs5


【解决方案1】:

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

handle 方法中发出1 会影响重新进入调用,该调用会看到-1 发出的startWith之前返回Observable.empty - 作为@ 987654327@值是同步发出的。

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

添加delay 可防止重新进入呼叫。

【讨论】:

  • 嗯,我不太相信这种解释——对我来说它看起来像一个错误。一旦switchMap 切换到下一个流,前一个流应该被取消订阅并且它的发射被忽略。
  • 一开始我也有同样的想法。但是.switchMap 工作正常,正如您所描述的那样。仔细看看:source$.next(1).empty() 返回之前执行。换句话说,.empty 是第二个,interval 是第一个。
  • 今天玩得更多了,现在对我来说很有意义。谢谢你,很抱歉造成不必要的混乱。
  • “添加延迟可防止重新进入呼叫。”我认为这种说法是不正确的。 delay 导致 empty() observable 抢占 interval() observable,所以 switchmap() 丢弃前者并执行后者
猜你喜欢
  • 2020-05-12
  • 2021-12-08
  • 2016-12-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-18
  • 2020-07-10
  • 1970-01-01
相关资源
最近更新 更多