Combining Streams with concat

concat merges multiple observable streams and emits values from each input stream in a strict sequential order. At any given moment, only one subscription is active, and its values flow directly to the observer. When the currently active stream finishes, the operator subscribes to the next observable in line. Values produced by any of the combined sequences are passed through as part of the output stream — a mechanism commonly described as flattening in RxJS literature.

The operator proceeds through the following steps:

  1. Subscribe to the first observable in the sequence
  2. Forward each emitted value to the observer
  3. Upon completion of the current source, subscribe to the next one in line
  4. Notify the observer of completion only after every source observable has completed
  5. If any source throws an error, propagate the error notification to the observer immediately

Keep in mind that concat cannot terminate if any input stream never completes. Consequently, any subsequence streams will never be subscribed to in such a scenario.

The diagram below illustrates how concat handles two streams A and B, each yielding 3 items. The results are delivered in order — first all values from A, then all from B:

Concat operator diagram

When to Use

concat – RxJS Reference — figure 2

Reach for this operator when the order of emissions matters and you want values from earlier-passed streams to surface first. A common scenario involves a cache-backed observable combined with a server-backed observable. Using concat ensures that cached values appear before any remote data.

Below is a practical example that applies concat to two streams:

const a = interval(500).pipe(map((v) => 'a' + v), take(3));
const b = interval(500).pipe(map((v) => 'b' + v), take(3));

concat(a, b).subscribe((value) => console.log(value));

Interactive Demo

Further Reading