concatMap operator is basically a combination of two operators - concat and map. The map part lets you map a value from a source observable to an observable stream. Those streams are often referred to as inner streams. The concat part works like concatAll - it combines all inner observable streams returned from the map and sequentially emits all values from every input stream.

    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.

    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.

    The operator works in the following way:

    1. Subscribe to a source observable
    2. When a new value arrives from a source observable, execute a map function that returns an inner observable
    3. Subscribe to this inner observable
    4. When this inner observable emits a value, pass it down to an observer
    5. When a new value arrives from a source observable, execute a map function that returns an inner observable
    6. Put this inner observable in a queue
    7. Once the current inner observable completes, subscribe to the next inner observable in the queue
    8. Only after source observable completes and all inner observables complete, send the complete notification to the observer.
    9. If any of the inner observables throws an error, send the error notification to the observer.

    The following diagram demonstrates this sequence of steps:

    Progress: NaN%

    Link to this section

    This operator is mostly used when you need to map a plain value to an observable. A common use case is mapping URL strings into HTTP requests. As opposed to mergeMap, concatMap allows to execute all requests in a sequence - only once the previous request completes, a new request is initiated via subscription.

    Here’s an example of using concatMap to do exactly this:

    const urls = [ '', '' ]; from(urls).pipe( concatMap((url) => { return fromFetch(url); }) ).subscribe((response) => console.log(response.status));

    Link to this section

    Additional resources
    Link to this section

    See also
    Link to this section