What is the reason behind Rxjs switchMap only emitting the final value from an of() observable source?

Here are two code snippets, one using map and the other using switchMap.

The functionality of map is clear:

of('foo', 'bar')
  .pipe(map((val) => sanitizer(val)))
  .subscribe((val) => console.log('value:', val));

function sanitizer(val: string) {
  return val;
}

Output:

value: foo
value: bar

However, when using switchMap, only the last value is printed. Why does this happen?

One assumption could be that map is for synchronous operations while switchMap is for asynchronous operations (like returning observables or promises).

of('foo', 'bar')
  .pipe(switchMap((val) => sanitizer(val)))
  .subscribe((val) => console.log('value:', val));

async function sanitizer(val: string) {
  return val;
}

Output:

value: bar

You can view the demonstration on StackBlitz: StackBlitz Demo

Answer №1

switchMap switches to a new observable and cancels the previous one when new values come in. If you want to maintain order, use concatMap - it resolves the first observable before moving on to the second (order preserved).

of emits values immediately after each other, so the first value doesn't get resolved.

of('foo', 'bar')
  .pipe(concatMap((val) => sanitizer(val)))
  .subscribe((val) => console.log('value:', val));

async function sanitizer(val: string) {
  return val;
}

Answer №2

Due to the synchronous nature of the `of` function, when used in combination with the `switchMap` operator, the inner observable is unsubscribed immediately upon receiving a new emission from the outer one. This results in both emissions being received almost simultaneously, leading to the first one being discarded and only the second one being utilized for further processing within the projection function.

Answer №3

According to the information provided in the RxJS documentation about switchMap:

This function transforms each source value into an Observable that is then combined in the output Observable, emitting values only from the most recently transformed Observable.

It's important to note that RxJS follows a push-based approach. When switchMap receives a value, it starts processing it immediately. If another value comes in while processing is still ongoing, switchMap will switch to handling the new value and abandon the current Observable or Promise.

This behavior proves particularly beneficial in situations where there are frequent updates like when typing in a search field where only the latest input should trigger result retrieval:

input$.pipe(
  switchMap(input => http.get(`/api/search?q=${input}`))
).subscribe(result => console.log(result));

However, if you need to address each input sequentially without interruption, consider using concatMap instead of switchMap.

I hope this explanation clarifies things for you!

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Accessing information from a database in ReactJS and passing the resulting promises to the return function via the .then method

Summary; I am currently working on integrating data from an API into my React application upon loading to ensure immediate availability. I am open to revising and restructuring the code if necessary, as long as I can achieve this functionality. It seems th ...

The vanishing act: Semantic UI menu disappears when you click

My objective is to create a persistent left-side menu using Semantic-UI. I want to implement two different states for the menu - one with text for each item and another with an image for each item. However, I am facing some challenges that have me complete ...

What is the reason behind having 3 watchers for 1 binding in AngularJS?

Take a moment to view the screenshot provided below https://i.sstatic.net/qLcem.png In the screenshot, it is evident that there are #3 watchers for a single binding. Would someone care to explain the reason behind this? P.S: I am utilizing AngularJS Ba ...

Compelling users to provide feedback on an App with the Ionic Framework

As a novice developer, I could use some assistance with implementing ratings in my app. My goal is to show menu items based on whether a user has given my app a 5-star rating. For instance, if a user gives a 5-star rating, I would assign the class "review ...

Tips for Structuring Code in a Resource Management Phaser Typescript Project

I'm currently developing a resource-management game and require a "collection manager" to streamline interactions between states and objects in Typescript. Let's imagine the game revolves around nurturing cats. In one state, players advance time ...

Setting a blank value or null equivalent to a field: Tips and tricks

Here is the component state that I am working with: interface Person { name: string; surname: string; } interface CompState{ //...fields ... person?: Person; } render() { if(this.state.person){ const comp = <div>{this. ...

Tips for effectively using the parseInt function to access and verify a span element from inside a chrome extension

Trying to utilize parseInt to ascertain if a span element is greater than or equal to 1 within my Google Chrome Extension. Attempting to monitor this "0" for changes and trigger a specific URL upon change - Refer to the Image View of the "inspect" option ...

Guide on Implementing Right-to-Left (RTL) Support in Material UI React

Currently, I am in the process of developing an application designed for LTR usage, but I am interested in adding RTL support as well. The application itself is built on top of Material UI React. By using CSS Flex Box, I have managed to rotate the applicat ...

Using AngularJS, passing a value from outside a directive to the directive and detecting changes in the

As a newcomer to AngularJs, I am facing a challenge in retrieving data from outside a directive. The scenario involves multiple input fields being updated and the necessity for the directive to process this information. For instance, consider the code sni ...

Normalization of Firebase Database

Recently, I developed a Tricycle Patrol app designed to address the prevalent issue of reckless tricycle drivers in our city. Users can log in and submit reports through a form that includes fields such as: - created_at - description - lat - lng - plateNu ...

Leveraging JavaScript Functions in HTML

I am having an issue with a JavaScript file containing two similar functions that are executed through an HTML form. While the first function runs smoothly, the second function does not display correctly. It seems like I might be calling or executing the ...

Creating adaptable rows and columns with Angular Material's data table feature

My approach to rendering dynamic rows and columns using a basic table was successful: <tbody> <tr *ngFor="let row of data"> <td *ngFor="let val of row"> {{ val }} </td> </tr> </tbody> </ ...

Improve Email Regular Expression to Restrict Consecutive Periods

I'm not very good with regular expressions, so I decided to seek some help. Here's the regular expression I have: /[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.) ...

The search is on for the elusive object that Angular 2/4

Why am I encountering the error message saying "Cannot find name 'object'"? The error message is: Error: core.service.ts (19,23): Cannot find name 'object'. This error occurs in the following line of code: userChange: Subject<ob ...

What is the best approach to resolving the MongoServerError: E11000 duplicate key error?

Index.Js File: const cookieSession = require("cookie-session"); const express = require("express"); const app = express(); const helmet = require("helmet"); const morgan = require("morgan"); const dotenv = require(&q ...

Angular textbox with dynamic concatenated name functionality

Hello, I'm currently working with some code that looks like this: <div *ngFor="let phone of phoneList; let phIndx = index;"> <div class="peoplePhoneTxtDiv"> <input [disabled]="phone.disabled" class="peoplePhoneTxtBox" type="text" ...

Using Vue.js to dynamically append router links with JavaScript

let link = `<router-link :to="{name : 'profile' , params : { slug : ${response.data.nickname} }}"> <img src="${response.data.avatar}" class="card__image"> </router-link>`; $('body').appen ...

Having trouble retrieving alert message after submitting form using jquery

Trying to submit a form using jQuery, but when clicking on the submit button it displays a blank page. I understand that a blank page typically means the form has been submitted, but I want to show an alert() for testing purposes instead. However, it only ...

Removing a modal div element in React after navigating

import React, { useState } from "react"; import { useNavigate } from "react-router-dom"; import axios from "axios"; import Cookies from "js-cookie"; const LoginPage = () => { const [email, setEmail] = useState( ...

Incorporate a unique identifier $id within the ajax request

Whenever I make changes to my product, I would like the categories to show up in a dropdown menu. Currently, it only displays: -- Select your category -- For instance, if my $current_category_id = 2, I want the dropdown to show the relevant categories. ...