Reputation: 14013
I read the documentation of switchMap and map, but I still don't completely understand the difference. Are there some cases where it does not make a difference at all?
Upvotes: 65
Views: 72184
Reputation: 165
Swtichmap --> it will switch to new observable
Ex: Imagine you have product listing page with a filter text box.
As a developer what we will do is we will create on keypress for test box and for each event we will make a api call which returns us a observable.
Imagine user entered 4 keys in textbox, now 4 observables are subscribed which is not a good or optimal solution.
With using switch map, we will cancels the last emitted observables.
Upvotes: 0
Reputation: 2889
Map - It acts relatively similar to map in Arrays. map
takes in every value emitted from the Observable
, performs an operation on it.
var observable = Rx.Observable.interval(1000);
var observer = {
next: function(value) {
console.log(value);
}
};
observable.map(function(value) {
return value*10;
}).subscribe(observer);
SwitchMap - switchMap will subscribe to all the inner Observables inside the outer Observable but it does not merge the inner Observables. It instead switches to the latest Observable and passes that along to the chain.
Let’s assume that each orange vertical line at the top represents 1 second. This means that the outer Observable (OO) emits values at 1, 4, and 5.5 seconds while the inner Observable (IO) emits values every second for 3 seconds, starting immediately after subscription (time zero).
The first three output values (10, 10, 10) seem pretty easy. Just multiply 1 x 10 = 10 for each of them according to the operator logic. Based on these first three values, we could say that for each OO value, the IO emits all of its values.
This assumption seems to hold true for the first output value of 30… And the second output value of 30…
But shouldn’t it emit a final value of 30??
This is where the switchMap logic comes in. Every time the OO emits a value, the IO emits all of its values unless the OO emits a new value before the IO finishes emitting all of its values. We can see this when the OO emits a value of 5 and it appears that our last value of 30 is “canceled”.
Projects each source value to an Observable which is merged in the output Observable, emitting values only from the most recently projected Observable.
var button = document.querySelector('button');
var obs1 = Rx.Observable.fromEvent(button, 'click');
var obs2 = Rx.Observable.interval(1000);
obs1.switchMap(
event => {
return obs2
}
).subscribe(
(value) => console.log(value)
);
In above example, no matter how many time I click the button, I am always going to get the values starting from 0 because switchMap
switches to the latest observable.
Best use case is when we want to make an API call based on data received from outer observable.
Read more -
https://zach-gollwitzer.medium.com/how-to-read-an-rxjs-marble-diagram-f6e8dfa29781 https://dev.to/bhagatparwinder/map-vs-mergemap-vs-switchmap-5gee https://blogs.msmvps.com/deborahk/higher-order-observable/
Upvotes: 15
Reputation: 3425
see the definitions of 2 functions:
map<inputType, outputType>(syncFunction: (input: inputType) => outputType )
switchmap<inputType, Observable<outputType>>( asyncFunction: (input: inputType) => Observable<outputType> )
map = an asynchronous function calls a synchronous function (asyncTask => syncTask)
switchMap = an asynchronous function calls an asynchronous function sequentially (asyncTask => asyncTask )
example for switchMap:
observable1 calls observable2 means:
observable1_event1 => new observable2 asynchronous => Task1
observable1_event2 => new observable2 asynchronous => Task2
observable1_event3 ...
If observable1_event2 is emitted when task1 is not completed, the Observable2 of task1 will be rejected by calling unsubscribe(). It means Task1 will not show output any more after that.
If observable1_event2 is emmitted when task1 was completed. all outputs of Task1 will be showed normally then outputs of task2 will be showed.
Note that: each new observable2 can trigger many events (observable2_event1, observable2_event2,...)
Upvotes: 7
Reputation: 6956
Instead of a textual explanation, I always prefer visual explanation.
Map -
Upvotes: 27
Reputation: 1722
Both operators are different.
switchMap: Maps values to observable. Cancels the previous inner observable.
fromEvent(document, 'click')
.pipe(
// restart counter on every click
// First click: 0, 1, 2...
// Second click: cancels the previous interval and starts new one. 0, 1, 2...
switchMap(() => interval(1000))
)
.subscribe(console.log);
map: Add projection with each value.
//add 10 to each value
const example = source.pipe(map(val => val + 10));
Upvotes: 54
Reputation: 14679
Are there some cases where it does not make a difference at all?
No. They are two totally different beasts. switchMap
is expected to return an observable, map
can return anything. Their application is different. It would typically go like this:
someStream$.pipe(
switchMap(args => makeApiCall(args)), // must return a stream
map(response => process(response)) // returns a value of any shape, usually an object or a primitive
).subscribe(doSomethingWithResults);
There are other operators similar in nature to switchMap
: mergeMap
(AKA flatMap
), exhaustMap
, concatMap
(and there are cases when all those amount to more or less the same thing), but not map
.
Upvotes: 14