【问题标题】:Rx.Subject loses eventsRx.Subject 丢失事件
【发布时间】:2017-01-22 01:25:21
【问题描述】:

谁能解释这 3 个变体之间的区别?

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

  1. 首先按预期工作,处理所有事件。
  2. 但是第二个输了最后一个事件(3)
  3. 第三次输掉第二次事件(2)

您能否帮助我了解问题所在以及如何使第三个变体处理所有事件?

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

【问题讨论】:

    标签: javascript rxjs rxjs5 ngrx


    【解决方案1】:

    这一切实际上都是预期的行为。

    令人困惑的是,当您多次重复使用 Subject 和诸如 take() 之类的运算符时会发生什么。

    运算符take(1) 只接受一个值并发送complete 通知。由于.subscribe(bs2),Subject 收到此通知。现在是最重要的部分。
    当Subject 收到complete 或error 通知时,它会将自己标记为已停止。这意味着它永远不会汇出任何项目或通知,这在 Rx 中是正确且预期的行为。通知complete 或error 必须是最后的发射。

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

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

    你第三个demo的过程完全一样。

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

    【讨论】:

    • 哦,谢谢,这很有意义。但是,我尝试根据您的建议修复它,现在第二个变体正在工作。但是第三条仍然丢失了第二条消息。 jsfiddle.net/e9cm00tg 顺便说一句,这意味着ngrx 中的@Effects 工作错误?我永远不会将任何 Completed 集合返回到结果中?但在他们的例子中,他们发送数组作为结果,据我了解它有效吗?github.com/ngrx/example-app/blob/master/src/app/effects/…
    • 我不知道您期望的“第二条消息”是什么。我建议您单独测试它,而不要弄乱其他示例。这个jsfiddle.net/yphp4q5L 的行为应该如此。请注意您使用的是switchMap(),第二个switchMap() 返回Rx.Observable.empty()(这只是complete 通知)。
    • 我明白了,jsfiddle.net/vhunpu66 现在可以了。意味着我们不能只为一个效果发送两条消息。在这种情况下,我们重写等待可观察对象(将其切换到另一个)。并且合并阻止接收到主题的完成事件。
    • 我的主要想法是了解 Ngrx 中的效果如何工作。我试图让它变得简单并测试:) 谢谢!
    • 我不知道这是如何在ngrx 中实现的。使用 merge() 操作符,合并后的 Observable 会发送 complete 通知,merge() 会自动取消订阅。也许尝试简化您想做的事情,因为您的演示不是那么简单并发布另一个问题。顺便说一句,如果您不确定每个操作员确实查看了源代码,因为它通常并不难理解。例如toArray()github.com/ReactiveX/rxjs/blob/master/src/operator/toArray.ts
    猜你喜欢
    • 2011-09-17
    • 2010-12-15
    • 2015-01-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多