【问题标题】:RxJS pushing the current value to late subscribersRxJS 将当前值推送给迟到的订阅者
【发布时间】:2014-08-19 11:15:00
【问题描述】:

以下是我使用的 HTML sn-p 示例:

<html>
<head>
    <script src="rx.all.js"></script>
</head>
<body>
    <script>
        var source = new Rx.BehaviorSubject(function() {return 2;});

        var stuff = source.scan([], function(val, operation) {
            return operation(val);
        });

        stuff.subscribe(function(v) {
            console.log("first subscriber");
            console.log(v);
        });

        source.onNext(function(val) {
            return val * 2;
        });

        stuff.subscribe(function(v) {
            console.log("second subscriber");
            console.log(v);
        });
    </script>
</body>

JS控制台的输出是:

first subscriber
2
first subscriber
4
second subscriber
0 

现在,“stuff”做了一些处理(基本上是对当前值应用一个函数),这是我从 ReactJs + RxJS (https://github.com/fdecampredon/react-rxjs-todomvc) 的 TodoMVC 示例中获得的想法。

我想要实现的输出是让第二个订阅者在订阅的那一刻也看到“4”。我将 RxJS 与 ReactJS 结合使用,因此组件在卸载时取消订阅(由于路由更改),并在再次安装时再次订阅。

【问题讨论】:

    标签: javascript reactive-programming rxjs


    【解决方案1】:

    使用 replay(1) 将您的 stuff 更改为热可观察对象,该可观察对象将记住最后一个值并将其提供给后来者:

    var stuff = ...;
    stuff = stuff.replay(1);
    
    // go ahead and start it listening
    // you could use .refCount() here also
    var subscription = stuff.connect();
    
    // now subscribe your observers
    stuff.subscribe(...);
    
    // send some results
    source.onNext(...);
    source.onNext(...);
    
    // subscribe another observer
    // will see the lastest value
    // as well as any new values
    stuff.subscribe(...);
    
    source.onNext(...);
    // ...
    

    【讨论】:

    • 目前,replay(1) 在 RxJS 中不起作用。您必须使用replay(null, 1)
    • replay(null, 1) 对 RxJS 4.1.0 没有任何帮助。改用replay(x =&gt; x, 1)
    【解决方案2】:

    为了更新这个问题,replay 现已从 rxjs 的运算符列表中删除。一种策略是使用shareReplay

    ...您知道您将有迟到的订阅者需要访问以前发出的值的流的情况。

    所以你想要类似的代码

    const $obs: Subject<boolean>;
    
    const $newSharedObs = $obs.pipe(
       shareReplay({bufferSize: 1, refCount: false })
    );
    
    $obs.next(true);
    
    //will log true even though subscribe is called after next
    $newSharedObs.subscribe(s => {
       console.log(s);
    });
    

    注意refCount: false,即使他们没有订阅者,它也会保持可观察的“热”:

    如果 refCount 为真,则源将被取消订阅一次 引用计数降至零,即内部 ReplaySubject 将是 退订。所有新订户都将从 新的 ReplaySubject 反过来会导致一个新的订阅 源可观察。另一方面,如果 refCount 为 false,则源 不会被取消订阅,这意味着内部 ReplaySubject 将 仍然订阅源(并且可能永远运行)。

    【讨论】:

      猜你喜欢
      • 2023-03-13
      • 1970-01-01
      • 2020-01-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-02-14
      • 1970-01-01
      相关资源
      最近更新 更多