switchMapTo在订阅之前创建可观察对象

9
我正在使用Date.now()编写一个计时器流,但是我不太理解一个细节。
当我使用switchMap编写流时,它可以正常工作,并且在start$开始发出事件后调用getTestStartTime$()。
let start$ = Observable.fromEvent(document.querySelector('#start'), 'click');
let stop$ = Observable.fromEvent(document.querySelector('#stop'), 'click');

let getTestStartTime$ = () => Observable.of(Date.now())
    .delay(sampleTime)
    .repeat()
    .takeWhile(val => true);

let time$ = start$
    .switchMap(event => getTestStartTime$())
    .map(startTime => Date.now() - startTime)
    .map(diff => diff / 1000)
    .takeUntil(stop$)
    .repeat();

但是,当使用switchMapTo替换switchMap时,似乎在start$触发之前就调用了该函数。我可以看到这一点,因为Date.now()被过早地调用了(它的时间与页面加载的时间相同)。

let time$ = start$
    .switchMapTo(getTestStartTime$()) // this calls getTestStartTime$ too early
    .map(startTime => Date.now() - startTime)
    .map(diff => diff / 1000)
    .takeUntil(stop$)
    .repeat();

谢谢。

我发现写.switchMap(getTestStartTime$)正常运作。但是我还是没有理解.switchMap和.switchMapTo之间的区别。 - skovmand
1个回答

43

由于您在构建流时调用了函数,因此它会提前调用。

switchMap接受一个函数,当新值从上游到来时调用该函数。该函数的结果将被订阅为一个新的流。

switchMapTo接受一个Observable,每次从上游传来一个值,就会订阅该Observable。您可以通过调用getTestStartTime$()来创建Observable

当输出取决于从上游传来的值时,请使用switchMap;当实际上游值不相关且仅用作订阅信号时,请使用switchMapTo


20
那个最后一段对我来说很有价值。 - DarkNeuron
是的,我同意! - skovmand
1
这个例子可能会帮助您理解它是如何工作的。 - DiPix

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接