<ol id="log"></ol>
ol {
  list-style-type: none;
  padding: 0;
}
const { Observable, Observer, Subject } = rxjs;

const logEl = document.getElementById('log');
function log(message) {
  const li = document.createElement('li');
  const text = document.createTextNode(message);
  li.appendChild(text);
  logEl.appendChild(li);
}

const tapRefCount = (onChange) => (source) => {
  let refCount = 0;

  // mute the operator if it has nothing to do
  if (typeof onChange !== 'function') {
    return source;
  }
  
  // mute errors from side-effects
  const safeOnChange = (refCount, prevRefCount) => {
    try {
      onChange(refCount, prevRefCount);
    } catch (e) {
      console.error(e);
    }
  };
  
  // spy on subscribe
  return Observable.create((observer) => {
    const subscription = source.subscribe(observer);
    const prevRefCount = refCount;
    refCount++;
    safeOnChange(refCount, prevRefCount);
    
    // spy on unsubscribe
    return () => {
      subscription.unsubscribe();
      const prevRefCount = refCount;
      refCount--;
      safeOnChange(refCount, prevRefCount);
    };
  });
};

console.clear();
const subject = new Subject();
const stream = subject.pipe(
  tapRefCount((refCount, prevRefCount) => {
    log(JSON.stringify({ refCount, prevRefCount }));
  })
);

let subIntCount = 0;
const subscriptions = [];
const subInt = setInterval(() => {
  let subscription;
  subIntCount++;
  
  // stop
  if (subIntCount == 10) {
    while(subscription = subscriptions.pop()) {
      log('[unsubscribe]');
      subscription.unsubscribe();
    }
    clearInterval(subInt);
    log('[done]');
  }
  
  // unsubscribe... maybe
  if (subscriptions.length > 0 && Math.random() > 0.5) {
    log('[unsubscribe]');
    subscription = subscriptions.pop();
    subscription.unsubscribe();
    return;
  }
  
  // subscribe
  log('[subscribe]');
  subscription = stream.subscribe();
  subscriptions.push(subscription);
}, 1000);

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.2.1/rxjs.umd.js