Changing Behavior with MapTo

InstructorJohn Lindquist

Share this video with your friends

Send Tweet

You often need streams to trigger different behaviors on the data based on which streams triggers. This lessons shows how to use mapTo to pass functions into the scan operator and have completed control over you data.

Sam De Boni
~ 8 years ago

I made the following minor changes when working with RxJS 4.0.6:

  1. use flatMapLatest in place of switchMapTo
  2. use map in place of mapTo
  3. assign a function to inc that returns the increment function since map evaluates its argument
<pre> const Observable = Rx.Observable; const startButton = document.querySelector('#start'); const stopButton = document.querySelector('#stop'); const start$ = Observable.fromEvent(startButton, 'click'); const interval$ = Observable.interval(1000); const stop$ = Observable.fromEvent(stopButton, 'click'); const intervalThatStops$ = interval$ .takeUntil(stop$); const data = {count:0}; **const inc = ()=>(acc)=>({count:acc.count+1});** const reset = (acc)=> data; start$ **.flatMapLatest(intervalThatStops$)** **.map(inc)** .startWith(data) .scan((acc,curr)=> { return curr(acc); }) .subscribe((x)=>console.log(x)); </pre>
nader dabit
~ 8 years ago

Thanks for putting this up here, great to know!

nader dabit
~ 8 years ago

@Sam, flatMapLatest is giving me an error, "start$.flatMapLatest is not a function", on version "5.0.0-beta.6"

Noah Rawlins
~ 8 years ago

with rxjs 5.0.0 beta 7 I had to do this to get his behavior. Note the <any> type on the mapTo. This makes sure it doesn't complain about trying to start an Observable that now emits functions with a plain object in startWith()

start$
  .switchMapTo(intervalThatStops$)
  .mapTo<any>(inc)
  .startWith(data)
  .scan((acc, curr) => curr(acc) )
  .subscribe((x) => console.log(x));
ganqqwerty
~ 6 years ago

I didn't understand your intention on 01:08:

What we need to do to make .scan() flexible enough to switch between these on its own is to pass a function down the stream.

In the end of the example I don't see scan function switching between behaviours, but the whole thing is much harder to read now. Can you point me maybe to another example where I can see the need of such change?

Don
~ 6 years ago

Why .mapTo instead of .map? you don't make clear what .mapTo IS and why to use... can you clarify? The only way i can understand what you say is that, .map will process each event in the stream with the passed-in function and send the result of that downstream,... whereas .mapTo sends the passed-in function itself ('inc') downstream without processing each event. is this true? thanks

J. Matthew
~ 5 years ago

Why .mapTo instead of .map? you don't make clear what .mapTo IS and why to use...

To quote mapTo's documentation: Like map, but it maps every source value to the same output value every time.

In other (more) words, you'd typically use map to modify the incoming value in some way, e.g.

[1,2,3].map(x => 2 * x) = [2,4,6]

But in this case we don't use or care about the incoming value; we just want to replace it entirely, using the same constant each time. In this case we're replacing it with a function, inc. We could still do this with map:

.map(x => inc)

But we're not using x, so it doesn't need to be there. We could also do:

.map(() => inc)

But we're still writing a function when all we want to do is return inc. That's why mapTo exists:

.mapTo(inc)

This is cleaner and better communicates the intention.