Rx.Subject丢失事件

时间:2017-01-22 01:25:21

标签: javascript rxjs rxjs5 ngrx

有人可以解释这三种变体之间的区别吗?

http://jsfiddle.net/8vx2g3fr/2/

  1. 首先作为感知,所有事件都被处理。
  2. 但是第二次输掉了最后一场比赛(3)
  3. 第三次失败(2)
  4. 请问您能帮助我了解问题是什么以及如何使第三个变体处理所有事件?

    1

    let bs = new Rx.Subject();
    bs
        .subscribe(v=>{
            console.log("in", v);
            if (v % 2 == 0) {
                setTimeout(()=>{
                    console.log(" out", v, "->" , v + 1);
                    bs.next(v+1);
                }, 0);
            }
        });
    
    bs.next(0);
    bs.next(2);
    

    输出:

    in 0
    in 2
     out 0 -> 1
    in 1
     out 2 -> 3
    in 3
    

    2

    let bs2 = new Rx.Subject();
    bs2
        .subscribe(v=>{
            console.log("in", v);
            if (v % 2 == 0) {            
                Rx.Observable.interval(0).take(1)
                    .map(()=>{console.log(" out", v, "->" , v + 1);return v+1;})
                    .subscribe(bs2);
            }
        });
    
    bs2.next(0);
    bs2.next(2);
    

    输出:

    in 0
    in 2
     out 0 -> 1
    in 1
     out 2 -> 3
    

    3

    let bs3 = new Rx.Subject();
    bs3
        .switchMap(v=>{
            console.log("in", v);
            if (v % 2 == 0) {            
                return Rx.Observable.interval(0).take(1)
                    .map(()=>{console.log(" out", v, "->" , v + 1);return v+1;});
            }
    
        return Rx.Observable.empty();     
        }).subscribe(bs3);
    
    bs3.next(0);
    bs3.next(2);
    

    输出:

    in 0
    in 2
     out 2 -> 3
    in 3
    

1 个答案:

答案 0 :(得分:4)

这实际上是预期的行为。

令人困惑的是,当您多次重复使用Subjecttake()等运算符时会发生这种情况。

运营商take(1)仅获取一个值并发送complete通知。由于Subject.subscribe(bs2)会收到此通知。现在是最重要的部分 当Subject收到completeerror通知时,它会将自己标记为已停止。这意味着永远不会汇出任何项目或通知,这是Rx中的正确和预期行为。通知completeerror必须是最后一次排放。

所以Subject由第一个take(1)完成,由值0bs2.next(0)调用)触发。

然后当值2触发Observable.interval(0).take(1)收到的Subject的第二次运行时,它会被自动忽略,因为Subject已标记为已停止。

第三个演示中的过程完全相同。

您可以在Subject.ts中的源代码中看到它: