对于具有特定 RxJS 版本的特定 Observable 链,排放顺序将始终相同。
正如已经提到的,在 RxJS 4 中它使用currentThread
调度程序,如下所示:https://github.com/Reactive-Extensions/RxJS/blob/master/src/core/perf/operators/range.js#L39 https://github.com/Reactive-Extensions/RxJS/blob/master/src/core/perf/operators/range.js#L39.
所有调度程序(除了immediate
来自 RxJS 4) 是内部使用某种类型的队列 https://github.com/Reactive-Extensions/RxJS/blob/master/src/modular/scheduler/currentthreadscheduler.js#L29所以顺序总是一样的。
事件的顺序与您在图中显示的非常相似(......或者至少我认为是这样):
-
1
被调度并发出,因为它是队列中唯一的操作。
-
100
已安排。此时调度程序的队列中没有更多操作,因为2
尚未安排。这RangeObservable
在调用后递归地安排另一个发射onNext() https://github.com/Reactive-Extensions/RxJS/blob/master/src/modular/observable/range.js#L19。这意味着100
被安排在之前2
.
-
2已安排 https://github.com/Reactive-Extensions/RxJS/blob/master/src/modular/observable/range.js#L20.
-
100
被发射,101
已安排
-
2
被发射,101
被处置。
- ... 等等
请注意,这种行为在 RxJS 4 和 RxJS 5 中是不同的。
在 RxJS 5 中,大多数 Observables 和运算符默认不使用任何 Scheduler(一个明显的例外是需要处理延迟的 Observables/operator)。所以在RxJS 5 的RangeObservable不会安排任何事情 https://github.com/ReactiveX/rxjs/blob/9ec444e1a053a882d714b9cb4bc92c898152e4b7/src/observable/RangeObservable.ts#L89并立即开始循环发出值。
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