如何在RXJS中传输异步流?

时间:2017-04-14 20:57:08

标签: javascript rxjs

我正在尝试了解流如何通过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的情况下稍微延迟到达

我在这里缺少什么?管道如何在这里工作?

2 个答案:

答案 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会对要执行的操作进行排队。

所以:

    发出
  • 1
  • flatMapLatest创建Rx.Observable.range(x*100, 2);可观察并订阅它,这会导致100的排放,以及101的排放安排。
  • 在此之前,会发出2,因此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. 1已安排并发出,因为它是队列中的唯一操作。
  2. 100已安排。此时,计划程序队列中不再有任何操作,因为尚未安排2RangeObservable schedules another emission recursively after it calls onNext()。这意味着100计划在2之前安排。{/ li>
  3. 2 is scheduled
  4. 100已发出,101已安排
  5. 发出
  6. 2101已被处理。
  7. ......等等
  8. 请注意,此行为在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