Suggest an editImprove this articleRefine the answer for “What does ConcatMap do?”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)**concatMap** is an RxJS operator that processes inner Observables sequentially, one at a time, queuing new values and waiting for the previous one to complete. **Key point:** concatMap preserves the order of operations, so it's a good fit for saving data, forms, and transactions, but it will hang if the inner Observable never completes.Shown above the full answer for quick recall.Answer (EN)ImageA great question, usually asked together with `switchMap`. ## In short (as in an interview) **concatMap** is an RxJS operator that **processes inner Observables sequentially, one at a time**, waiting for the previous one to complete. It **queues new values**. ## In detail `concatMap` is a mapping operator that: 1. takes a value from the source Observable 2. creates an inner Observable 3. **waits for it to complete** 4. only then starts the next one ### Example ```ts import { of } from 'rxjs'; import { delay, concatMap } from 'rxjs/operators'; of(1, 2, 3).pipe( concatMap(v => of(v).pipe(delay(1000))) ).subscribe(console.log); ``` Result: ``` 1 (after 1s) 2 (after 2s) 3 (after 3s) ``` Even though the values arrive immediately, they execute **sequentially**. ## Visually ``` source: a----b----c concatMap: inner a: ----- inner b: ----- inner c: ----- result: ----- ----- ----- ``` ## When concatMap is used When it matters to **preserve the order of operations**. For example: - saving data - submitting forms - writing to a database - a queue of API requests - uploading files Angular example: ```ts this.saveClicks$.pipe( concatMap(data => this.api.save(data)) ).subscribe(); ``` Each save runs strictly in order. ## Difference from switchMap | Operator | Behavior | |---|---| | switchMap | cancels the previous one | | concatMap | queues | | mergeMap | runs in parallel | | exhaustMap | ignores new ones | ## Important point `concatMap` works correctly **only if the inner Observable completes**. If it never completes, the queue will hang. For example: ```ts concatMap(() => interval(1000)) // a bad idea ``` ## A typical follow-up question In an interview, they often ask: **When is concatMap better than switchMap?** Answer: when **operations must not be lost** and the order of execution matters. Example: - saving form steps - a message queue - transactions ## A simple cheat sheet (frequently asked) You can answer like this: > switchMap - cancels > concatMap - one at a time > mergeMap - in parallel > exhaustMap - ignoresFor the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.