Search code examples
javascripttypescriptrxjs

What's the point of mapTo in RxJs?


I'm reading the docs for mapTo and I'm simply not getting the point of that operator's existence. I get what it does but the two line below should produce equivalent result.

const outcome = "bzzz";
const result1 = source.map(a => outcome);
const result2 = source.mapTo(outcome);

Yet, the creators of RxJs chose to increase complexity by adding an extra method. It seems pointless as such, so I'm suspecting there's more to it than what meets the eye.

What's the point of having a dedicated operator for such a specific case?


Solution

  • The differences between map and mapTo

    At first sight, we can see that map accepts a callback function

    function map<T, R>(project: (value: T, index: number) => R, thisArg?: any)
    

    whereas mapTo accepts a static value

    function mapTo<R>(value: R)
    

    So, a clear difference is that map's callback function can generate a value depending on the arguments provided. This is not the case for mapTo, where you just simply provide a value that will be always passed along to the next subscriber in the chain. If you will, mapTo(value) can be though of as

    map(() => value)
    

    We can also deduce this from the source code:

    // `mapTo`
    () => subscriber.next(value)
    
    // `map`; `project` is the provided callback function
    () => subscriber.next(project.call(thisArg, value, index++));
    

    But you might not want to do that, why call a function when you can directly use a value?

    Some use cases

    A use case might be when you have a NgRx effect and you want to return the same, non-dynamic, action, when something happens.

    createEffect(
      () => this.actions.pipe(
        /* some logic here... */
        mapTo(staticAction('a message here')),
      )
    );
    

    Another one, which might not seem very practical, is when you want to simulate some requests coming in:

    merge(
      timer(300).pipe(mapTo("req#1")),
      timer(600).pipe(mapTo("req#2")),
      timer(100).pipe(mapTo("req#3")),
      timer(900).pipe(mapTo("req#4")),
    ).pipe(
      /* some complicated logic here... */
    )
    

    Anyway, the point of this operator is, at least from my perspective, to indicate that you want to pass along static values, thus values that are not dependent on data from the previous subscriber.