交换操作员如何取消订阅先前的观测值?

时间:2019-03-23 05:06:13

标签: javascript asynchronous rxjs reactive-programming

我正在尝试理解可观察的事物。 当我使用开关操作符时,我听不懂这行“它取消订阅以前的可观察对象,并订阅新的”。

var inp=document.getElementById("i");
var t=Rx.Observable.fromEvent(inp,"keyup");
t.map((e)=>Rx.Observable.range(1,3)).subscribe((e)=>console.log(e))
///t.map((e)=>Rx.Observable.range(1,3)).switch().subscribe((e)=>console.log(e))

每当我按下输入框中的任何键时,我都会得到没有开关操作员的输出:

RangeObservable {start: 1, rangeCount: 3, scheduler: CurrentThreadScheduler}
rangeCount: 3
scheduler: CurrentThreadScheduler {}
start: 1
__proto__: ObservableBase

但是当我在map运算符之后使用switch运算符时,输出更改为1,2,3。 交换机操作员在内部做什么?

1 个答案:

答案 0 :(得分:1)

在进行t.map((e)=>Rx.Observable.range(1,3))时,t本身是输入事件中的Observable,然后从那里将其映射到 nested Observable的Observable,该Observable将发出整数从1到3。

现在,您在其上应用switch运算符,该运算符实际上作用于Observable of Observable。对于您而言,t.map(..)通过调用内部的Rx.Observable.range(1,3)来创建内部Observable的Observable。

因此,一旦Rx.Observable.range(1,3)发出了一个Observable,切换操作员就会从t.map(...)调用中取消订阅Observable,并订阅Rx.Observable.range(1,3)调用中的最新Observable。

根据switch运算符的documentation,请注意单词最新

  

Switch订阅一个发出Observable的Observable。每一次   它观察到这些发射的Observable之一,Observable返回   由Switch取消订阅先前发出的Observable开始   从最新“可观察”中发射物品。

要将代码更改为不使用switch,您需要从t.map(...)调用中订阅嵌套的Observable:

t.map((e)=>Rx.Observable.range(1,3)).subscribe((e)=> e.subscribe(e => console.log(e)))

,它将在控制台中输出1, 2, 3。因此,switch使其更加优雅,而不是订阅嵌套的Observable,只需在发射后立即切换即可。

t.map((e)=>Rx.Observable.range(1,3)).switch().subscribe((e)=>console.log(e))
                       //  ^
                       //  |_________________ now this Observable is subscribed as soon as it is emitted.

这里是演示如何订阅内部Observable以获得没有switch的1、2、3:

var inp=document.getElementById("input");
var t=Rx.Observable.fromEvent(inp,"keyup");
console.log("** Without Switch ***")
t.map((e)=>Rx.Observable.range(1,3)).subscribe((e)=> e.subscribe(e => console.log(e)));
<script src="https://npmcdn.com/@reactivex/rxjs@5.0.0-beta.6/dist/global/Rx.umd.js"></script>
Enter something: <input type="text" id='input'>

这里与switch相同:

var inp=document.getElementById("input");
var t=Rx.Observable.fromEvent(inp,"keyup");
console.log("** With Switch ***")
t.map((e)=>Rx.Observable.range(1,3)).switch().subscribe(e=> console.log(e));
<script src="https://npmcdn.com/@reactivex/rxjs@5.0.0-beta.6/dist/global/Rx.umd.js"></script>
Enter something: <input type="text" id='input'>