我正在尝试了解流如何通过RXjs中的管道传输 我知道这不应该是一个问题,因为这是异步流的整个想法 - 但仍然有我想要理解的东西。
查看此代码:
var source = Rx.Observable
.range(1, 3)
.flatMapLatest(function (x) { //`switch` these days...
return Rx.Observable.range(x*100, 2);
});
source.subscribe(value => console.log('I got a value ', value))
结果:
I got a value 100
I got a value 200
I got a value 300
I got a value 301
我相信(IIUC)图表是这样的:(通知标记为101,201,取消订阅)
----1---------2------------------3------------------------------|
░░░░░░░░flatMapLatest(x=>Rx.Observable.range(x*100, 2))░░░░░░░░
-----100-------(-̶1̶0̶1̶)-------200---(-̶2̶0̶1̶)-----300------301-------------
以下是问题:
问题:
是否始终保证2将在(101)之前到达?那个3是在(201)之前到达的吗?
我的意思是 - 如果我不想看时间线,那么下面的图表就完全合法了:
----1---------------2---------------3------------------------------|
░░░░░░░░flatMapLatest(x=>Rx.Observable.range(x*100, 2))░░░░░░░░
-----100-------101------200---201-----300------301-------------
2
在已经发出101的情况下稍微延迟到达
我在这里缺少什么?管道如何在这里工作?
答案 0 :(得分:1)
我想你已经明白了“管道”这个问题。正如你所说的那样。无论如何,在这里查看数据如何沿着订阅链向下流动仍然很好:Hot and Cold observables : are there 'hot' and 'cold' operators?
此答案中未涉及的是数据流的调度。数据确实按顺序发出,这是合同的一部分。但是,数据发射的时间由用于该可观察量的调度程序定义。每个运营商都有许多合理的默认值,这使得大多数时候我们甚至不必考虑调度。
很难确定此处发生了什么,但最好的猜测是range
会在Rx.Scheduler.currentThread
调度程序schedules work as soon as possible on the current thread.
上发出所有值。
Scheduler.Immediate将确保未安排操作,而是立即执行。 Scheduler.CurrentThread确保对其执行操作 进行原始呼叫的线程。这与Scheduler.Immediate不同, 因为CurrentThread会对要执行的操作进行排队。
所以:
flatMapLatest
创建Rx.Observable.range(x*100, 2);
可观察并订阅它,这会导致100的排放,以及101的排放安排。101
被删除3
相同但后来没有新值,因此没有什么可以阻止在流端收到301。这可以在以下jsfiddle中观察到:http://jsfiddle.net/ukhtwwcz/
究竟为什么它在细节中表现得如此,我无法确定。
答案 1 :(得分:1)
对于具有此特定RxJS版本的此特定Observable链,排放顺序将始终相同。
如前所述,在RxJS 4中,它使用currentThread
调度程序,如您所见:https://github.com/Reactive-Extensions/RxJS/blob/master/src/core/perf/operators/range.js#L39。
所有调度程序(RxJS 4中的immediate
除外)均为internally using some type of a queue,因此顺序始终相同。
事件的顺序与你在图表中显示的非常相似(......或者至少我认为是这样):
1
已安排并发出,因为它是队列中的唯一操作。100
已安排。此时,计划程序队列中不再有任何操作,因为尚未安排2
。 RangeObservable
schedules another emission recursively after it calls onNext()
。这意味着100
计划在2
之前安排。{/ li>
2
is scheduled。100
已发出,101
已安排2
,101
已被处理。请注意,此行为在RxJS 4和RxJS 5中有所不同。
在RxJS 5中,大多数Observable和运算符默认不使用任何Scheduler(一个明显的例外是Observables / operator需要处理延迟)。所以在RxJS 5 the RangeObservable
won't schedule anything并开始在循环中立即发射值。
RxJS 5中的相同示例将产生不同的结果:
const source = Observable
.range(1, 3)
.switchMap(function (x) {
return Observable.range(x * 100, 2);
});
source.subscribe(value => console.log('I got a value ', value));
这将打印以下内容:
I got a value 100
I got a value 101
I got a value 200
I got a value 201
I got a value 300
I got a value 301
但是,如果添加例如delay(0)
,这将发生重大变化。常识表明这不应该做任何事情:
const source = Observable
.range(1, 3)
.switchMap(function (x) {
return Observable.range(x * 100, 2).delay(0);
});
source.subscribe(value => console.log('I got a value ', value));
现在只有内部RangeObservable
被安排并重复处理几次,这使得它只发出最后一个RangeObservable
的值:
I got a value 300
I got a value 301