RxJS检测可观察对象何时被订阅

11

我需要检测一个可观察对象(observedEvents)被订阅后,再订阅另一个可观察对象(triggerEvent)。我不想手动订阅triggerEvent,而是在observedEvents有订阅时只订阅一次。

以下是一些说明代码:

// This just emits events
let emitting = new EventEmitter();

// This is the main Observable which someone else might
// have access to
let observedEvents = Rx.Observable.merge(
  Rx.Observable.fromEvent(emitting, 'aba'),
  Rx.Observable.fromEvent(emitting, 'bob')
)

// This trigger should get a subscription if observedEvents
// has one, i.e. when I subscribe to observedEvents
// that subscription activates this trigger

// I have made an attempt at this by calling skipUntil
// this however skips one event, but I don't want that
let triggerEvent = Rx.Observable.merge(
  // these actions are things that can
  // happen when the trigger is active
  Rx.Observable.of('a').delay(200),
  Rx.Observable.of('b').delay(400),
  Rx.Observable.of('c').delay(600)
)
.skipUntil(observedEvents);

// Something else should be used to activate trigger
// I don't want to do this part manually
triggerEvent.subscribe(val => {
    console.log(`Do something fancy with ${val}`);
});

//----------------------------------------------------
// Somewhere else in the code...
//----------------------------------------------------
observedEvents.subscribe(evt => {
  console.log(`Some event: ${evt}`);
});
// At this point I want triggerEvent to become active
// because observedEvents has a subscription

setTimeout(() => {
  emitting.emit('bob', 'world');
  setTimeout(() => emitting.emit('aba', 'stackoverflow!'), 500);
}, 200);
<!DOCTYPE html>
<html>
<head>
  <script src="https://npmcdn.com/@reactivex/rxjs@5.0.0-beta.7/dist/global/Rx.umd.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/EventEmitter/5.1.0/EventEmitter.min.js"></script>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
</head>
<body>

</body>
</html>

这可行吗?

我希望我的解释能够说明我正在寻找的内容。

当我写这篇文章时,我认为使用主题可能是我需要的解决方案。虽然我不确定,但只要能指点一下正确的方向或提供可能的解决方案即可。

2个回答

13

对于rxjs > v7,请参见此答案


回答

果然我在使用Subjects方面是正确的。关键是Subject的观察者列表。以下是我最终所做的:

let emitting = new EventEmitter();
let sub = new Rx.Subject();

// return this to users
let myGlobalSub = sub.merge(Rx.Observable.of(1, 2, 3));

// For internal use
let myObservers = Rx.Observable.fromEvent(emitting, 'evt');

console.log(`The number of subscribers is ${sub.observers.length}`);

// Only do something if myGlobalSub has subscribers
myObservers.subscribe(l => {
  if (sub.observers.length) { // here we check observers
    console.log(l);
  }
});

// Somewhere in the code...
emitting.emit('evt', "I don't want to see this"); // No output because no subscribers

myGlobalSub.subscribe(l => console.log(l)); // One sub

emitting.emit('evt', 'I want to see this'); // Output because of one sub

console.log(`The number of subscribers is ${sub.observers.length}`);
<!DOCTYPE html>
<html lang=en>

<head>
  <script src="https://unpkg.com/rxjs@5.5.11/bundles/Rx.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/EventEmitter/5.2.5/EventEmitter.min.js"></script>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
</head>

<body>
</body>

</html>


4
"observers"现已被标记为过时,在v. 8中将成为内部使用。正在寻找解决此问题的方法... - PhiLho
1
@PhiLho 请看这个其他答案 - smac89

4

@smac89的答案使用了在RxJS 7中已被弃用并计划在版本8中删除的observers属性。

如果您只想知道Observable是否已被订阅,可以改用observed布尔属性。

目前没有与观察者数组真正等效的替代方法。

let emitting = new EventEmitter();
let sub = new rxjs.Subject();

// return this to users
let myGlobalSub = rxjs.merge(sub,rxjs.of(1, 2, 3));

// For internal use
let myObservers = rxjs.fromEvent(emitting, 'evt');

console.log(`Has the subject been subscribed to ? ${sub.observed}`);

// Only do something if myGlobalSub has subscribers
myObservers.subscribe(l => {
  if (sub.observed) { // here we check observers
    console.log(l);
  }
});

// Somewhere in the code...
emitting.emit('evt', "I don't want to see this"); // No output because no subscribers

myGlobalSub.subscribe(l => console.log(l)); // One sub

emitting.emit('evt', 'I want to see this'); // Output because of one sub

console.log(`Has the subject been subscribed to ? ${sub.observed}`);
<!DOCTYPE html>
<html lang=en>

<head>
  <script src="https://unpkg.com/rxjs@%5E7/dist/bundles/rxjs.umd.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/EventEmitter/5.2.5/EventEmitter.min.js"></script>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
</head>

<body>
</body>

</html>


在 RxJs 7.1 中新增了此功能,请检查您的版本以防找不到! - Yohan Dahmani
1
谢谢。您的答案已经链接给使用 rxjs > v7 的人们。 - smac89

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接