RxSwift Transforming Operators: map, flatMap, flatMapLatest and concatMap

Throwing light over commonly used operators

Credit: unsplash.com

map:

The Map operator applies a closure to each item emitted by the source Observable, and returns an Observable that emits the results of applied callback.

RxMarbles: map

In general, When you have an item emitted from observable and you want to transform them into other type but not an observable then map is preferred.

map over array has following characteristics:

  • It takes a closure as an argument,
  • Executes it on every element of the array you called it on and
  • Returns a new array with each element of the original array replaced with the result of calling the callback on it.

The only difference in using map() on Observables are that:

  • It returns a new Observable instead of returning a new array.
  • It executes every time the Observable emits a new item.
Input: 1โ€”โ€”โ€”โ€”โ€”2โ€”โ€”โ€”โ€”3โ€”โ€”โ€”โ€”โ€”|โ†’
Result: โ€œ1โ€โ€”โ€”โ€”โ€”โ€œ2โ€œโ€”โ€”โ€”โ€”โ€”โ€œ3โ€โ€”โ€”โ€”โ€”โ€”|โ†’
transformation using map operator

flatMap:

The flatMap operator transform the items emitted by an Observable into Observables, then flatten the emissions from those into a single Observable.

It applies a closure to each item emitted by the source Observable and returns an Observable that itself emit items.

RxMarbles: flatMap
Input: 1 โ€”โ€” 2 โ€”โ€” 3 โ€”โ€” |โ†’
Intermediate:
Observable(โ€œ1โ€)โ€”โ€”โ€”โ€”โ€”|โ†’
Observable(โ€œ2โ€)โ€”โ€”โ€”โ€”โ€”|โ†’
Observable(โ€œ3โ€)โ€”โ€”โ€”โ€”|โ†’
Result: โ€œ1"โ€”โ€”โ€”โ€”โ€œ2โ€โ€”โ€”โ€”โ€”โ€œ3โ€โ€”โ€”โ€”โ€”|โ†’
transformation using flatMap operator

In general, what flatMap does is it applies a closure to each emitted Observable and returns an Observable. It internally subscribes to each of these Observable, merges them and finally results in an flatten array.

Note that FlatMap merges the emissions of these Observables, so that they may interleave.

FlatMap operator doesnโ€™t care about the order of the items. It creates a new observable for each item and that observable lives its own life. Some of them will emit faster, and others slower because we delay each of them for a random amount of seconds.

Here is a simple thumb-rule to decide as when to use flatMap() over map() in Rx's Observable.

If what you're returning as an end result of your transformation is:

  • a non-observable object then youโ€™d use just map(). map() wraps that object in an Observable and emits it.
  • an Observable object, then youโ€™d use flatMap(). flatMap() auto subscribes to inner observables, unwraps the Observable, gets the returned object, wraps it with its own Observable and emits it.

Another example of flatMap:

Item emitted from inner observable even when newer observable started emittingย elements

flatMapLatest:

The only difference between flatMap and flatMapLatest is it disposes previous subscription when new subscription happens.

Whenever a new item is emitted by the source Observable, it will unsubscribe to and stop mirroring the Observable that was generated from the previously-emitted item, and begin only mirroring the current one.

concatMap:

Map values to inner observable, subscribe and emit in order. The only difference between flatMapLatest and concatMap is it preserves the order of items. It has one flow also, not good for asynchronous operations as waits for observable to finish all items in sequence.

You can catch me at:

Linkedin: Aaina Jain

Twitter: __aainajain

If you have any suggestions for the next post write to me at aainajain100@gmail.com.