I have a need to detect when an observable (observedEvents
) has been subscribed to, and then subscribe to another observable (triggerEvent
). I don't want to subscribe to triggerEvent
manually, but only once and when observedEvents
has a subscription.
Here is some code explaining what I am looking for:
// 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/[email protected]/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>
Is this possible?
I hope that explains what I'm looking for.
As I'm writing this, I'm thinking a solution with Subjects is probably what I need. I'm not sure, but I just need a nudge in the right direction or a solution if possible.
Sure enough I was right about using Subjects. The key was the observers list for Subject. Here is what I finally did:
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/[email protected]/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>
The answer by @smac89 use the observers
property which has been deprecated in RxJS 7 and is scheduled to be removed in version 8.
If you only want to know if an Observable has been subscribed to, you may use the observed
boolean property instead.
There is currently no real equivalent to the observers array.
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>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With