Exploring the issue of nested subscriptions causing bugs in Angular

My current challenge involves nesting subscriptions within "subscribe" due to the dependency of some data on the response of the previous subscription. This data flows down the subscription chain until it is stored in an array.

Starting with an array of IDs, I make a call to a service to convert those IDs to Objects. The code structure for this process looks like:

idArray.forEach(id =>
     this.getObjByID(id)));
}

getOjByID(ID: number): void {
  this._APIService.getObjByID(ID).subscribe(
    obj => {
        this.getDefaultConfig(obj);
    });
}

After retrieving these Objects, I then proceed to obtain a configuration file for each Obj. The relevant code snippet is as follows:

  getDefaultConfig(obj: any): void {
      this._APIService.getDefaultConfig(obj.id).subscribe(
          res => {
              obj.config = res;
              this.getPrices(obj);
          });
  }

Finally, the Object and its configuration are passed to a final subscription where a price object is added to the Object. Subsequently, the Object is pushed to an array of objects which are then rendered on the screen. The last piece of code for this process is outlined below:

  getPrices(obj: any): void {
      this._PriceService.getPrice(obj).subscribe(
          res => {
              obj.price = res;
              this.objs.push(obj);
          });
  }

I am encountering a bug related to the behavior of the subscribe/observables concept in my implementation. While the intended outcome is for the chain of actions to be executed for each ID present in my idArray, there seems to be instances where certain subscriptions or functions are being duplicated. Although no errors are displayed in the console, the issue is noticeable by the count of items in the final array "objs".

In an attempt to resolve this issue, I experimented with adding ".first()" or ".take(1)" before ".subscribe" across all functions. This adjustment managed to eliminate duplicate obj objects in the objs array, however, they all shared the same "price" object.

I am seeking insights into what could potentially be incorrect with my utilization of observables leading to this unexpected behavior?

Answer №1

Your problem may stem from an unexpected behavior when subscribing to the same Observable multiple times. This issue arose for me when I was caching API responses using my service.

The issue occurs because when you subscribe to an observable for a second time, the value is retrieved again (as it's considered a "hot" observable), causing the first subscription to also receive the new (or same) value. Consequently, your subsequent layers of functions are triggered twice (or more if there are additional subscribers).

To resolve this, you can simply add .share() at the end of your observable wherever it is created. For instance, here's a snippet from my current project:

const resp = this.http.get(url)
  .map( /* Perform operations and return a value */ )
  .catch(this.handleError)
  .share();

return resp;

A helpful explanation that really clarified things for me can be found here:

You mentioned that after making this adjustment, your final objects became null. It's possible that this could be due to some other issue in the code. However, I'm sharing this solution as it resolved the problem for me in a similar scenario.

(I had encountered the same issue with three levels of subscriptions, but everything worked fine once I added .share in my case.)

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

Angular2: AuthGuard malfunctioning with browser navigation controls

My AuthGuard setup works flawlessly during normal navigation within the application (see code below). Now, consider this scenario: A user goes to /content/secured-content, which requires authentication => they are redirected to /authentication/login due ...

Transferring SetState from a parent component to a child component in React Native

When working with React js, passing setState from parent components to child components is done like this. However, in React Native setABC is undefined. What is the recommended approach for achieving similar functionality in React Native? Parent.js: funct ...

Is it possible to invoke a helper function by passing a string as its name in JavaScript?

I'm encountering a certain issue. Here is what I am attempting: Is it possible to accomplish this: var action = 'toUpperCase()'; 'abcd'.action; //output ===> ABCD The user can input either uppercase or lowercase function ...

What is causing my component to render the count value twice?

This is my main layout component: function MainPage() { return( <div> <MLayout children={<MNavbar custOrFalse={false} />} /> </div> ); } export default MainPage; Here is the child navbar compone ...

Begin the NextJS project by redirecting the user to the Auth0 page without delay

I am new to coding and currently working on a project using Typescript/NextJS with Auth0 integration. The current setup navigates users to a page with a login button that redirects them to the Auth0 authentication page. However, this extra step is unneces ...

What is the best way to incorporate Ekko Lightbox into an Angular 7 Project?

I'm facing an issue while implementing Ekko lightbox in my angular project. Specifically, I want to use it in a certain component but I am unsure about how to import the necessary files into that component. After installing Ekko via NPM, I found all ...

What can be done to ensure that the a href tag is functioning as clickable?

Having an issue with my HTML and CSS code for a notification dropdown box. I am unable to click the tag, even after attempting to use JavaScript. Can't seem to figure out what's causing this problem. Any advice on how to make the tag clickable? ...

Close the menu when clicking anywhere on the page body

I have successfully implemented a dropdown menu that opens when the navigation button is clicked. However, I am struggling to find a way to close the dropdown menu when the mouse clicks on any part of the page's body. If you have a solution for this ...

Nodejs application encountering a problem with the findUser method in Active Directory

I have encountered an issue while using the activedirectory npm package with Nodejs v16.18.1. The code snippet below is used for authentication and finding user details: Could someone please assist with this? async authUserActiveDirectory(usernameAD: stri ...

The content inside the bootstrap modal is not visible

My goal is to trigger a modal window when a specific div is clicked using bootstrap modal. However, upon clicking the div, the screen darkens but the modal body fails to appear. Code: <html> <head> <title></title> ...

Making an asynchronous request from jQuery to a Slim Framework API endpoint

I'm currently working on incorporating Slim into my project and I'm facing some challenges with setting up the AJAX call correctly: $.ajax({ url: "/api/addresses/", type: 'POST', contentType: 'application/j ...

What is the process of accessing JSON data transmitted from a Express server in JavaScript?

Working with a node server, I've set up a client-server model, meaning the client connects to "localhost" and express generates a response based on certain logic. While I'm able to send a JSON object through the response, I'm unsure of how t ...

Refreshing an HTML table using instance variables from a C# class (utilizing jQuery and AJAX)

Explore <script type="text/javascript"> $(document).ready(function () { $("#viewDetails").click(function () { $.ajax( { type: "POST", url: '@Url.Action("GetDetail", "ControllerName")' ...

Excessive requests to location or history APIs in a brief period of time

Alert: Reached maximum update depth. This issue may arise when a component invokes setState within useEffect without a dependency array, or if any of the dependencies change on each render. const OwnerPage = () => { const onOpen = useAgencyModal((s ...

How to Resolve ENOENT ERROR When Using fs.unlink in an Express.js Simple Application?

Currently, I am developing a basic blog using express.js. For managing the posts, I have opted for Typicode/lowdb as my database. The posts are created, updated, and deleted based on unique IDs stored in a data.json file. Additionally, I utilize the slug d ...

What are the steps for modifying the fields within the form?

The HTML code displays a table of todo items with options to delete or edit each entry. <tr *ngFor="let todo of todos; let i=index"> <td>{{ todo.name }}</td> <td>{{ todo.designation }}</td> <td>{{ todo.compa ...

Issues with audio and video playback intermittently occurring on Sencha Touch 2

As a beginner with Sencha Touch 2, I am currently working on uploading images onto an iPad using Xcode. My app has audio playing on the home screen, and I want the video to start playing and the audio to stop when a specific tab is selected. However, the ...

When the flex-grow property is set to 1, the height of the div extends beyond the space that

Here is an example of some HTML code: .container { height: 100%; width: 100%; display: flex; flex-direction: column; padding: 10px; background-color: aqua; } .box { width: 100%; height: 100%; flex-grow: 1; background-color: cadetb ...

Disable a tab or menu item if the bean's boolean value is 'false'

I designed a home page with various menu/tab options that redirect the user when clicked, but only if they have access to that specific item. If access is not granted, the menu item becomes unclickable. While this functionality works, I am interested in en ...

When the key code is equal to "enter" (13), the form will be submitted

When I press the Enter key, I want to submit a form if there are no error messages present. Here is the function I have created: $(targetFormID).submit(function (e) { var errorMessage = getErrorMessage(targetDiv); if (e.keyCode == 13 && errorMessa ...