【问题标题】:RxJS: How to subscribe to inner observable only when outer observable/subject is subscribed to?RxJS:如何仅在订阅外部可观察/主题时订阅内部可观察?
【发布时间】:2018-06-23 12:50:06
【问题描述】:

背景

使用 Typescript 和 RxJS,我正在尝试扩展一个行为主体,以便它将一个可观察对象作为构造参数,然后订阅它,以便将来自可观察对象的每个值设置为行为主体的值。

问题

当行为主体本身至少有一个订阅者时,如何使行为主体仅订阅内部可观察对象?

代码

import { Observable } from 'rxjs/Observable';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';

export class SubjectWithInnerObservable<T> extends BehaviorSubject<T> {

    constructor(
        initialState: any,
        someObservable: Observable<T>
    ) {
        super(initialState);

        // I only want this subscription to exist when there are one or more subscribers to the behavior subject
        someObservable.subscribe(this);
    }
}

【问题讨论】:

  • 你为什么要这个?主体本身也是可观察的并产生值,那么让行为主体发出值有什么问题?
  • 我删除了一堆上下文以消除噪音并专注于我需要帮助的部分。当至少有一个订阅者时,注入的 observable 实际上来自连接到 websockets 的服务。如果不是必须的,我不希望这种联系存在。此外,在将 observable 分配给行为主体之前,实际上会出现复杂的映射/转换值,但我不想展示这一点。
  • 这是一个行为主题,因为存储在其中的值实际上是通过 observable 获得的值的累积,我希望新订阅者获得累积值。
  • 我会封装BehaviorSubject而不是扩展它。
  • is only subscribed ... when ... has at least one subscriber 听起来像refCount

标签: javascript typescript rxjs reactive-programming rxjs5


【解决方案1】:

您可以在 websocket 上使用.publishBehavior() 运算符,该运算符内部有一个 BehaviorSubject。

“发布”位意味着它在连接之前不会发射,就像在软管上的水龙头一样。

添加.refCount() 运算符,您可以在订阅时自动连接,即由订阅计数控制的点击。

文档:RefCount

演示

// mock websocket
const ws = new Rx.Subject()

const autoConnected = ws
  .do(x => console.log('ws emits', x)) // just to show ws stream
  .publishBehavior(null)  // make connectable, i.e only emit when subscribed
  .refCount()             // auto-connect on subscribe
  .filter(x => x)         // filter out that pesky initial value

ws.next(1) // before subscription - never emits

const subscription = autoConnected.subscribe(x => console.log('1st subscription', x))
ws.next(2)
ws.next(3)

subscription.unsubscribe()
ws.next(4)  // after unsubscribe - never emits

autoConnected.subscribe(x => console.log('2nd subscription', x))
ws.next(5) // after re-subscription - emits last plus next
.as-console-wrapper { max-height: 100% !important; top: 0; }
&lt;script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.5.6/Rx.js"&gt;&lt;/script&gt;

【讨论】:

  • 这简直太完美了。我不会承认我写了多少行代码来尝试完成你在 5. 中所做的事情。Kudos man。感谢您的宝贵时间。
猜你喜欢
  • 2019-05-11
  • 2017-04-13
  • 1970-01-01
  • 1970-01-01
  • 2020-02-26
  • 2018-07-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多