The subscription for the second Observable in RxJS concatMap is triggered individually

I am currently developing an Angular 6 application. I want the app to display a loading animation whenever there is a change in the route or if there are any pending HTTP requests. To achieve this, I have set up two Observables as follows: For httpPendingRequests, I have implemented a counter using Angular's HttpInterceptor; and for locationChanged, I am subscribing to Router's NavigationStart/NavigationEnd events.

httpPendingRequests: BehaviorSubject<number>;
locationChanged: BehaviorSubject<boolean>;

To subscribe to these two Observables, I am using concatMap with the following code:

this.locationChanged.pipe(
  concatMap(changed => {
    console.log('location change:' + changed);
    if (changed) {
      return this.httpPendingRequests;
    } else {
      return of(0);
    }
  }),      
  map(count => count > 0)
).subscribe(val => { 
  console.log('isloading: ' + val);
});

My expectation was that this would only log 'isloading' to the console when both the location has changed and there are pending requests. It does work as expected in this case. However, I noticed that it also logs the 'isloading' message even when there are only pending HTTP requests without any change in location. This situation confused me because I thought that the operator would ensure that the Observables are subscribed in order. If the first one (location change) does not emit, then the second one (pending request) should not be triggered. Am I misunderstanding this concept?

In addition, I tried other methods like zip, forkJoin, combineLatest to combine Observables, but they all behaved the same way by triggering the subscription only once. I am uncertain about what went wrong with them either.

If more information is needed, feel free to ask. Thank you in advance!

Answer №1

To find a solution, one can utilize the combineLatest observable along with the map operator. For a demonstration, visit: https://stackblitz.com/edit/so-rxjs-concat.

The relevant code can be found in the app.component.ts file. Refer to the output in the console.log for further insights.

Answer №2

Consider the use of BehaviorSubject in your code.

BehaviorSubject always requires a value to emit upon creation, ensuring that locationChanged will always emit at least one notification.

If you opt for Subject, you have more control over when the first notification is emitted.

In this snippet extracted from your code, no logs are produced because locationChanged never emits:

const httpPendingRequests = new BehaviorSubject<number>(0);
const locationChanged = new Subject<boolean>();

locationChanged.pipe(
    concatMap(changed => {
      console.log('location change:' + changed);
      if (changed) {
        return httpPendingRequests;
      } else {
        return of(0);
      }
    }),      
    map(count => count > 0)
  ).subscribe(val => { 
    console.log('isloading: ' + val);
});

setTimeout(() => {
    httpPendingRequests.next(1);
}, 100);
setTimeout(() => {
    httpPendingRequests.next(2);
}, 200);
setTimeout(() => {
    httpPendingRequests.next(3);
}, 300);

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

Each time new scripts are loaded, the Angular 13 window.ng.ɵcompilerFacade gets swapped out for a fresh

New Update: After observing the behavior of loading components/modules in my application, I have noticed a conflict arising between window.ng.ɵcompilerFacade and v13 compliance format when switching between Angular versions. The issue occurs when loading ...

A variety of personalized Vimeo play buttons

Recently, I stumbled upon a genius solution by Chris Coyier for creating custom Vimeo play buttons. It worked perfectly for my needs, but now I'm facing a challenge - how to make it function with multiple videos on the same page. I tried swapping out ...

Typescript fetch implementation

I've been researching how to create a TypeScript wrapper for type-safe fetch calls, and I came across a helpful forum thread from 2016. However, despite attempting the suggestions provided in that thread, I am still encountering issues with my code. ...

Attempting to streamline this function in order to avoid running it nine separate times

I have created a day scheduler and successfully saved data in local storage for one hour field. However, I am looking for a way to streamline this function so that I can use it across all 8-hour fields without duplicating the code. Can someone provide me w ...

Using PHP to globally access a JavaScript object named

I have a collection of CSS attributes stored in a MySQL database that are accessed using PHP. These attributes need to be accessible to JavaScript once the page has finished loading. To achieve this, I loop through each row and create a JavaScript object ...

Adding jQuery namespace to AngularJS

I'm facing a bit of an issue here. I've implemented RequireJS to manage my modules and dependencies. To prevent cluttering the global namespace, I've set up the following configuration to avoid declaring $ or jQuery globally: require.confi ...

Is it possible for me to ensure that the argument passed to `res.write` is sent as one solid chunk?

When utilizing express' res.write method to send chunks back to the requestor, it is important to note that one call to res.write does not necessarily mean the argument passed will be received as a single chunk. This can complicate the process of pars ...

Issue - The 'defaultValue' is failing to load the state value, and the 'value' is not being updated when changed

My current setup involves an input field in my MovieInput.tsx file: <input id="inputMovieTitle" type="text" onChange={ e => titleHandleChange(e) } value={ getTitle() }> </input> This is how the titleHandleChange function ...

Material-UI slider in React keeps reverting back to zero value

Exploring the construction of an interface where selecting a radio option reveals distinct form elements. Once a slider is exposed, any value changes are stored in an object that is subsequently visible on the page. In this scenario, the object does get ...

Tips on retrieving an input value from a dynamic list

I am struggling to retrieve the correct value with JavaScript as it always shows me the first input value. Any help would be greatly appreciated! Thank you in advance! <html> <head> </head> <body> <?php while($i < $forid){ ...

Place a gap at a specific spot within the boundary line

Here is a CSS code snippet that displays a horizontal line: .horizontalLineBottom { border-bottom:solid #6E6A6B; border-width:1px; } Is it possible to add space at a specific position on this line? For example, _________________________________ ...

The issue of a malfunctioning react TypeScript map when used in conjunction with useContext

I am attempting to retrieve data from the TVMaze API using React, TypeScript, and useContext. Although I can display the data, the useContext does not update with the return value, so when I use the map function, nothing is displayed. Any advice on how to ...

Switch from Gulp-TSLint to Gulp-ESLint for enhanced code analysis!

I am currently in the process of updating a Gulp task that uses gulp-tslint to now use gulp-eslint. The code snippet below outlines the changes I need to make: const { src } = require('gulp'); const config = require('./config'); const ...

Incorporating Kekule.js into a TypeScript-based React application

Greetings, community! I've created a React app designed to help individuals in the field of chemistry share their work. To facilitate this, I came across a library called Kekule.js Here is the link Utilizing TypeScript poses a challenge as it requir ...

Overriding methods in Angular2

There are two components in my code - a parent component and a child component. The child component extends from the parent component. In the parent component, there is a method called open(). However, the child component tries to overload this method by a ...

You can use AJAX, JQuery, or JavaScript in PHP to upload a total of 7 files by utilizing 7 individual file input

My client has a unique request - they want to be able to upload a file in PHP without using the traditional <form> tag or a submit button. While I am familiar with file uploads in PHP, I am unsure of how to achieve this without utilizing the <for ...

Is there a way to effortlessly upload numerous files in one go when browsing with jquery or JavaScript?

Currently working on a web application and looking to enable multiple file upload functionality within a single browse session, as opposed to selecting one file at a time. The goal is for users to be able to easily select multiple files with just one clic ...

What is the best way to remove text messages from a channel that only allows images?

I have developed a Discord bot named YES with a specific text channel for images only. My goal is to program the bot to automatically delete any text messages in this channel and respond with "You cannot send text messages." However, I also want to create ...

The dimensions on Next.js pages exceed those of the viewport by a significant margin

I have recently encountered a perplexing issue where the dimensions of my webpage appear to be 2.7 times larger than the viewport, even when there is no content or styles applied. The strange part is that it seems as though the page has been scaled up, eve ...

An Ajax GET request will not be able to locate the JSON file

I am having issues retrieving Key and Values from a JSON file using the function provided. Despite placing the 'datafile.json' in the same directory, the code fails to execute the alert(weblink) function, while the alert('test 1') works ...