Skip to main content

Combination Operators

startWith

Emits this value first, before the values emitted by the observable.

import { startWith } from "rxjs/operators";
Code
const numbers$ = of(1,2,3);

numbers$.pipe(
startWith('a', 'b', 'c')
)
.subscribe(console.log)
Output
a
b
c
1
2
3
Practical Example
<div>
<h2 id="countdown"></h2>
<div id="message"></div>
<button id="abort">Abort Mission</button>
</div>
Practical Example
// element refs
const countdown = document.getElementById('countdown');
const message = document.getElementById('message');
const abortButton = document.getElementById('abort');

// streams
const counter$ = interval(1000);
const abortClick$ = fromEvent(abortButton, 'click');

const COUNTDOWN_FROM = 10;

counter$.pipe(
mapTo(-1),
scan((accumulator, current) => {
return accumulator + current;
}, COUNTDOWN_FROM),
takeWhile(value => value >= 0),
takeUntil(abortClick$),
startWith(COUNTDOWN_FROM)
)
.subscribe(value => {
countdown.innerHTML = value;
if (!value) {
message.innerHTML = 'Liftoff!'
}
})

endWith

Emits this value last, after the values emitted by the observable.

import { endWith } from "rxjs/operators";
Code
const numbers$ = of(1,2,3);

numbers$.pipe(
endsWith('x', 'y', 'z')
)
.subscribe(console.log)
Output
1
2
3
x
y
z

concat

Concat allows you to create an observable from multiple other observables. On subscription, the concat will subscribe to the observables in order.

import {concat, interval} from "rxjs";
Code
const interval$ = interval(1000)

concat(
interval$.pipe(take(3)),
interval$.pipe(take(2))
).subscribe(console.log)
Output
0
1
2
0
1

merge

Lets you subscribe to multiple observables and emits values as they occur. Creates an observable by merging together other observables. Merge should be used when the observables relate to each other and have a common solution.

import {merge} from "rxjs";
Code
const keyup$ = fromEvent(document, 'keyup');
const click$ = fromEvent(document, 'click');


merge(
keyup$,
click$
).subscribe(console.log)
Practical Example
// element refs
const countdown = document.getElementById('countdown');
const message = document.getElementById('message');
const pauseButton = document.getElementById('abort');
const startButton = document.getElementById('start');

// streams
const counter$ = interval(1000);
const pauseClick$ = fromEvent(pauseButton, 'click');
const startClick$ = fromEvent(startButton, 'click');

const COUNTDOWN_FROM = 10;

merge(
startClick$.pipe(mapTo(true)),
pauseClick$.pipe(mapTo(false))
).pipe(
// switchmap to counter
switchMap(shouldStart => shouldStart ? counter$ : of(null)),
mapTo(-1),
scan((accumulator, current) => {
return accumulator + current;
}, COUNTDOWN_FROM),
takeWhile(value => value >= 0),
startWith(COUNTDOWN_FROM)
)
.subscribe(value => {
countdown.innerHTML = value;
if (!value) {
message.innerHTML = 'Liftoff!'
}
})

combineLatest

CombineLatest creates an observable from a number of other variables. On subscription, it subscribes to all inner observables, after all observables have emitted at least one value it will emit the last value emitted from each observable as an array each time any of the observables emits a value.

import {combineLatest} from "rxjs";
Code
const keyup$ = fromEvent(document, 'keyup');
const click$ = fromEvent(document, 'click');


combineLatest(
[keyup$,
click$]
).subscribe(console.log)

Practical Example
combineLatest(
[keyupAsValue(first),
keyupAsValue(second)]
).pipe(
filter(([first, second]) => {
return !isNaN(first) && !isNaN(second)
}),
map(([first, second]) => first + second)
)
.subscribe(console.log)

withLatestFrom

withLatestFrom is similar to combineLatest, but it is a pipeable operator that takes in a secondary stream. The value will only be emitted if both subscriptions have a value when the first is activated. It will not occur when only the second one is activated.

Code
click$.pipe(
withLatestFrom(interval(1000))
).subscribe(console.log)

forkJoin

forkJoin takes in a number of observables and once all observables have completed it emits the last value emitted from each of them.

Code
const numbers$ = of(1,2,3);
const letters$ = of('a', 'b', 'c');

forkJoin(
[ numbers$, letters$]
).subscribe(console.log)

Output
[3, 'c']

If you'd rather output an object than an array you can do the following.

Code
const numbers$ = of(1,2,3);
const letters$ = of('a', 'b', 'c');

forkJoin(
{ numbers: numbers$, letters: letters$ }
).subscribe(console.log)

Output
{
letters: "c";
numbers: 3;
}