Learn RxJS
  • Introduction
  • Learn RxJS
    • Operators
      • Combination
        • combineAll
        • combineLatest
        • concat
        • concatAll
        • endWith
        • forkJoin
        • merge
        • mergeAll
        • pairwise
        • race
        • startWith
        • withLatestFrom
        • zip
      • Conditional
        • defaultIfEmpty
        • every
        • iif
        • sequenceEqual
      • Creation
        • ajax
        • create
        • defer
        • empty
        • from
        • fromEvent
        • generate
        • interval
        • of
        • range
        • throw
        • timer
      • Error Handling
        • catch / catchError
        • retry
        • retryWhen
      • Multicasting
        • publish
        • multicast
        • share
        • shareReplay
      • Filtering
        • audit
        • auditTime
        • debounce
        • debounceTime
        • distinct
        • distinctUntilChanged
        • distinctUntilKeyChanged
        • filter
        • find
        • first
        • ignoreElements
        • last
        • sample
        • single
        • skip
        • skipUntil
        • skipWhile
        • take
        • takeLast
        • takeUntil
        • takeWhile
        • throttle
        • throttleTime
      • Transformation
        • buffer
        • bufferCount
        • bufferTime
        • bufferToggle
        • bufferWhen
        • concatMap
        • concatMapTo
        • exhaustMap
        • expand
        • groupBy
        • map
        • mapTo
        • mergeMap / flatMap
        • mergeScan
        • partition
        • pluck
        • reduce
        • scan
        • switchMap
        • switchMapTo
        • toArray
        • window
        • windowCount
        • windowTime
        • windowToggle
        • windowWhen
      • Utility
        • tap / do
        • delay
        • delayWhen
        • dematerialize
        • finalize / finally
        • let
        • repeat
        • timeInterval
        • timeout
        • timeoutWith
        • toPromise
      • Full Listing
    • Subjects
      • AsyncSubject
      • BehaviorSubject
      • ReplaySubject
      • Subject
    • Recipes
      • Alphabet Invasion Game
      • Battleship Game
      • Breakout Game
      • Car Racing Game
      • Catch The Dot Game
      • Click Ninja Game
      • Flappy Bird Game
      • Game Loop
      • Horizontal Scroll Indicator
      • Http Polling
      • Lockscreen
      • Matrix Digital Rain
      • Memory Game
      • Mine Sweeper Game
      • Platform Jumper Game
      • Progress Bar
      • Save Indicator
      • Smart Counter
      • Space Invaders Game
      • Stop Watch
      • Swipe To Refresh
      • Tank Battle Game
      • Tetris Game
      • Type Ahead
      • Uncover Image Game
    • Concepts
      • RxJS Primer
      • Get started transforming streams with map, pluck, and mapTo
      • Time based operators comparison
      • RxJS v5 -> v6 Upgrade
Powered by GitBook
On this page
  • After all observables emit, emit values as an array
  • Why use zip?
  • Examples
  • Additional Resources
  1. Learn RxJS
  2. Operators
  3. Combination

zip

PreviouswithLatestFromNextConditional

Last updated 1 year ago

signature: zip(observables: *): Observable

After all observables emit, emit values as an array


πŸ’‘ Combined with or , zip can be used to time output from another source!


Why use zip?

This operator is ideal when you want to combine values from multiple observables in a pairwise fashion, like zipping together the teeth of a zipper. Imagine having two observables, where one emits values like "hot", "warm", "cold", and the other emits values like "coffee", "tea", "lemonade". Using the zip operator, you'd pair them together as "hot coffee", "warm tea", and "cold lemonade".

An everyday example is when you want to match information from two sources, like pairing names with their corresponding scores in a game. Picture an observable emitting player names and another emitting their scores. With zip, you can easily create pairs of [player, score], ensuring each player is associated with the correct score.

Be mindful that zip will only emit a value when all input observables have emitted a corresponding value. This means if one observable has emitted more values than another, the unmatched values will be held back until the other observable emits its next value. In some cases, this could lead to unpaired values, making it important to ensure your observables are synchronized.

Examples

Example 1: zip multiple observables emitting at alternate intervals

( | | )

// RxJS v6+
import { delay } from 'rxjs/operators';
import { of, zip } from 'rxjs';

const sourceOne = of('Hello');
const sourceTwo = of('World!');
const sourceThree = of('Goodbye');
const sourceFour = of('World!');
//wait until all observables have emitted a value then emit all as an array
const example = zip(
  sourceOne,
  sourceTwo.pipe(delay(1000)),
  sourceThree.pipe(delay(2000)),
  sourceFour.pipe(delay(3000))
);
//output: ["Hello", "World!", "Goodbye", "World!"]
const subscribe = example.subscribe(val => console.log(val));

Example 2: zip when 1 observable completes

// RxJS v6+
import { take } from 'rxjs/operators';
import { interval, zip } from 'rxjs';

//emit every 1s
const source = interval(1000);
//when one observable completes no more values will be emitted
const example = zip(source, source.pipe(take(2)));
//output: [0,0]...[1,1]
const subscribe = example.subscribe(val => console.log(val));

Example 3: get X/Y coordinates of drag start/finish (mouse down/up)

// RxJS v6+
import { fromEvent, zip } from 'rxjs';
import { map } from 'rxjs/operators';

const documentEvent = eventName =>
  fromEvent(document, eventName).pipe(
    map((e: MouseEvent) => ({ x: e.clientX, y: e.clientY }))
  );

zip(documentEvent('mousedown'), documentEvent('mouseup')).subscribe(e =>
  console.log(JSON.stringify(e))
);

Example 4: mouse click duration

// RxJS v6+
import { fromEvent, zip } from 'rxjs';
import { map } from 'rxjs/operators';

const eventTime = eventName =>
  fromEvent(document, eventName).pipe(map(() => new Date()));

const mouseClickDuration = zip(
  eventTime('mousedown'),
  eventTime('mouseup')
).pipe(map(([start, end]) => Math.abs(start.getTime() - end.getTime())));

mouseClickDuration.subscribe(console.log);

Additional Resources


( | | )

( )

( )

πŸ“° - Official docs

- In Depth Dev Reference

πŸŽ₯ πŸ’΅ - AndrΓ© Staltz

πŸ“ Source Code:

StackBlitz
jsBin
jsFiddle
StackBlitz
StackBlitz
zip
zip
Combination operator: zip
https://github.com/ReactiveX/rxjs/blob/master/src/internal/operators/zip.ts
interval
timer
StackBlitz
jsBin
jsFiddle