first vs take vs single

 

See how these RxJS operators differ in emission, throwing errors and completion, when applied to different source Observables:

const { rxObserver } = require('api/v0.3');
const { timer, interval, merge } = require('rxjs');
const { first, single, take, ignoreElements } = require('rxjs/operators');


// A stream — one value at 5ms, complete at 10ms
const a$ = merge(timer(5), timer(10).pipe(ignoreElements()));

a$.subscribe(rxObserver('A stream — one value at 5ms, complete at 10ms'));

a$.pipe(first())
  .subscribe(rxObserver('A :: first()'));

a$.pipe(take(1))
  .subscribe(rxObserver('A :: take(1)'));

a$.pipe(single())
  .subscribe(rxObserver('A :: single()'));


// B stream — two values at 5ms and 10ms, complete at 10ms
const b$ = interval(5).pipe(take(2));

b$.subscribe(rxObserver('B stream — two values at 5ms and 10ms, complete at 10ms'));

b$.pipe(first())
  .subscribe(rxObserver('B :: first()'));

b$.pipe(take(1))
  .subscribe(rxObserver('B :: take(1)'));

b$.pipe(single())
  .subscribe(rxObserver('B :: single()'));


// C stream — no values, complete at 10ms
const c$ = timer(10).pipe(ignoreElements());

c$.subscribe(rxObserver('C stream — no values, complete at 10ms'));

c$.pipe(first())
  .subscribe(rxObserver('C :: first()'));

c$.pipe(take(1))
  .subscribe(rxObserver('C :: take(1)'));

c$.pipe(single())
  .subscribe(rxObserver('C :: single()'));