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

Using R plotly to show an image when hovering over a location on a map

After successfully implementing the technique of displaying an image on hover in a regular R plotly chart, I encountered issues when trying to apply the same method to a plotly map. Specifically, the approach broke down and failed to display the image. Can ...

Data entered into DynamoDb using typedORM displays inaccurate Entity details

Whenever I add new entries to my local dynamoDb table using typeDORM within a lambda function, it seems to save the record with the incorrect entity information. For example, the GSI1PK GSI1: { partitionKey: 'PRO#{{primary_key}}', ...

Creating a PDF export of your grid using Kendo Grid is a straightforward

I've been facing a challenge while trying to export an entire page using Kendo Angular PDF. Everything works smoothly until I add a Kendo Angular Grid onto the page. The problem arises when certain rows go missing and extra blank space appears on some ...

Encountering issues when attempting to establish the initial date of a react DatePicker based on the user's timezone

I am currently working on a React project and facing an issue with setting the default date of a DatePicker component to the user's timezone received from an API. Despite several attempts, I keep encountering an error whenever I try to inject the date ...

How to resolve undefined callback when passing it to a custom hook in React Native

I'm facing an issue with passing a callback to my custom hook: export default function useScreenshotDetection(onScreenshot) { useEffect(() => { ... onScreenshot(); ... }, []); } Strangely, the callback is not being detected ...

A login page designed with jquery does not require resubmission

Encountering an issue where after submitting incorrect login credentials on a webpage, the ajax request fails to go through upon subsequent attempts. After scouring StackExchange for solutions, I have explored threads such as Why won't my jQuery form ...

Incorporating a HTML layout with a JS backdrop

I have successfully implemented a JavaScript background and now I want to apply this background across all my PHP files. The issue is that the HTML code either overlaps with the JS content or appears behind it. How can I resolve this? Below is the JS fil ...

Issue with displaying error message and disabling button as Keyup event fails to trigger

Is there a way to assess the user's input in real-time on an on-screen form to ensure that the pageName they enter is not already in the navbarMenuOptions array? If it is, I want to switch the visibility of displayName and displaySaveButton. However, ...

Understanding the fundamentals of parseInt() and radix conceptsORExploring

Could you clarify the concept of radix in relation to parseInt()? I'm struggling to grasp how the string argument varies with different bases/radix. ...

"Encountering a 405 error when transmitting information from an HTML file to a Python Flask server using 'GET / HTTP/1.1'

As someone who is brand new to the world of python and AJAX, I have been piecing everything together from various sources online including examples and Flask documentation. So far, I have managed to make some progress. My goal is to send latitude and longi ...

What can be done to ensure smooth functionality of my nested navigation menu on mobile devices?

I'm utilizing the incredible features of Base Web for my website. One of the components I am using is a menu with a child menu, based on this example. The menu works perfectly fine on desktop - when I hover over an option, the child menu appears. Howe ...

Ajax polling ceases the polling process when an internet connection is lost

My current setup involves a continuous ajax polling cycle where messages are pulled, processed, a wait period occurs, and then the process is repeated. Everything runs smoothly until a user disconnects from the internet, whether it be due to a simple actio ...

Automatically populate a dropdown menu with options based on the user's birth date

I successfully managed to populate the drop-down fields for months, days, and years. Furthermore, I was able to calculate the age of the user; however, I have restricted it to a maximum of 13 years. Check out the code snippet below: $('#reg-yr' ...

What is the correct method to remove an item from local storage?

Using localStorage, I have stored multiple objects in an array. Is there a way to remove just one object from this array? If I use localstorage.removeItem(keysofthelocalstorage), I can delete the entire array, but I specifically want to remove only certai ...

JavaScript not functioning properly with HTML loaded via .load()

I'm facing a perplexing dilemma: My issue revolves around this JS code: EDIT updated JS $(".img-thumb").on("click", function(){ // displaying the same behavior as .click() thumbID = $(this).attr("id"); console.log(thumbID); $(".gal-act" ...

Converting an Observable Array into a nested JSON structure

Having difficulty storing an array of information properly as JSON. A visual representation of the issue can be seen in this fiddle. Input a set of tags and check the console for output. Additional detail: An input captures a comma-separated list of tag ...

AJAX - Self-Executing Anonymous Function

I have a question that may seem trivial, but I want to make sure I'm heading in the right direction. I've created two different versions of an XMLHttpRequest wrapper, and both are functioning correctly. const httpRequest = function () { let ...

Display radio buttons depending on the selections made in the dropdown menu

I currently have a select box that displays another select box when the options change. Everything is working fine, but I would like to replace the second select box with radio buttons instead. Can anyone assist me with this? .sub{display:none;} <sc ...

Exploring Ways to Loop through a JavaScript Map in Angular with ng-repeat

As I work on developing my Angular application, I encounter a situation where I have a Map object with keys and values (as demonstrated below). These key-value pairs in the map object (headerObj) are provided by the user as input to the application. var ...

Guide to Utilizing the Import Function in a Vue 3 Template

Working on a Vue 3 project, my setup includes a stuff.ts file with helpful functions that I need to utilize in my template. <script lang="ts"> import { defineComponent, onMounted } from 'vue' import { doSomething } from ' ...