24 Jul 2024
5 min

concatAll – RxJS Reference

concatAll

concatAll combines a number of inner observable streams and sequentially emits all values from every given input stream. It is similar to concat, but instead of taking a set of streams directly as input, it takes an observable source that produces other streams (observables). Those streams are often referred to as inner streams.

The operator only has one active subscription at a time from which the values are passed down to an observer. Once the current active stream completes it subscribes to next observable in a sequence. As values from any combined sequence are produced, those values are emitted as part of the resulting sequence. Such process is often referred to as flattening in documentation.

The operator works in the following way:

  1. Subscribe to a higher-order source observable
  2. When a new inner observable is emitted from the source observable, subscribe to it
  3. When a new value arrives from this inner source observable, pass it down to an observer
  4. When a new inner observable is emitted from the source observable, put it in a queue
  5. Once the current source observable completes, subscribe to the next source observable in the queue
  6. Only after all source observables complete, send the complete notification to the observer.
  7. If any of the inner source observables throws an error, send the error notification to the observer.

Please note that concatAll will never complete if some of the input streams don’t complete. This also means that some streams will never be subscribed to.

In the diagram below you can see the H higher-order stream that produces two inner streams A and B. The concatAll operator combines values from these two streams and then passes them through to the resulting sequence as they occur. As opposed to mergeAll, it subscribes to those inner observables sequentially. First it subscribes to A, waits until it’s completed, and only then subscribes to B.

The following diagram demonstrates this behavior:

concatAll operator diagram

Usage

Use this operator if the order of emissions is important and you want to first see values emitted by streams that come through the operator first. For example, you may have an observable sequences that delivers values from a cache and another sequence that delivers values from a remote server. Use concatAll if you want to combine them and ensure that the value from cache is delivered first.

Here’s an example of using concatAll to combine two streams:

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

higherOrderObservable.pipe(concatAll()).subscribe((value) => console.log(value));

Playground

Additional resources

See also

Frequently asked questions

How do I combine multiple observables in order with concatAll in RxJS?

Use concatAll() on a higher-order observable that emits inner observables, such as of(a, b).pipe(concatAll()). The operator subscribes to the first inner observable, passes its values downstream, and only subscribes to the next one after the current stream completes. This guarantees that values from earlier streams always appear before values from later ones.

What is the difference between concatAll and mergeAll in RxJS?

concatAll() subscribes to inner observables sequentially, waiting for each to complete before subscribing to the next one in the queue. mergeAll() subscribes to all inner observables immediately and emits values as they arrive, so their order is not guaranteed. Choose concatAll() when emission order matters, and mergeAll() when you want concurrent processing.

Why does concatAll never complete when an inner observable does not complete?

concatAll() sends the complete notification only after the source and all queued inner observables have completed. If any inner stream never completes, the operator stays subscribed to it and never moves on to the next stream in the queue, so the resulting observable never completes. Use take() or a similar operator on infinite streams to make them finish.

When should I use concatAll instead of concat in RxJS?

Use concat() when you already have a fixed set of observables to join in order. Use concatAll() when the observables arrive as values of a higher-order observable, so you don't know them in advance. A typical case is combining a cache stream with a remote server stream so that cached values are always delivered first.

Share this post

Sign up for our newsletter

Stay up-to-date with the trends and be a part of a thriving community.