In Angular, the issue arises when subscriptions are triggered multiple times upon navigating to various pages and then returning

I am faced with a challenge where I have two functions, A and B. My goal is to have both of these functions run when the component loads, specifically on ngOnInit. However, I need function B to only run after function A has completed execution because B relies on values from A. To achieve this, I have encapsulated function B inside function A. Function A involves observables, leading to multiple subscription calls when navigating to different pages and returning back.

Within my code for function A, I need to populate two separate objects - data: any and array1.

Here is an example of the code for function A:

ngOnInit(){
    A();
}

A(){
    this.service1.getData().subscribe((resp)=>
        if(resp){
            
            this.service2.dataFor.pipe(skipWhile((val)=>val ===null )).subscribe((response)=>{
           
            })
        }
    )
}


B(){
    if(this.data && Object.keys(this.data).length>0){
        this.service3.getValidity(this.data.data).subscribe((resp)=>{
        if(resp){
            
            console.log("from B if");

        }
        
        else if(this.array1.length===0){
            this.service3.getValidity('').subscribe((res)=>{
               
                console.log("from B else");
            })
        }
        })
    }
}

To address the issue of multiple subscription calls, I initially attempted to call function B inside function A like so:

A(){

    this.service1.getData().subscribe((resp)=>
        if(resp){
            
            
            this.service2.dataFor.pipe(skipWhile((val)=>val ===null )).subscribe((response)=>{
           
          
            B();
            
            })
        }
    )
}

However, this approach resulted in repeated subscription calls. The output was displayed as 'from B if' twice initially, and increased by one upon each navigation to another page and return.

Considering that unsubscribed subscriptions could be the cause, I made sure to include an onDestroy hook:

ngOnDestroy(){
     
}

The full reference code snippet includes a more structured approach with proper handling of subscriptions:

A(){
    this.subscription1=this.service1.getData().subscribe((resp)=>
        if(resp){
           
            
            this.subscription2=this.service2.dataFor.pipe(skipWhile((val)=>val ===null )).subscribe((response)=>{
            
            
            
            })
        }
    )
}


B(){
    if(this.data && Object.keys(this.data).length>0){
        this.subscription3=this.service3.getValidity(this.data.data).subscribe((resp)=>{
        if(resp){
            
        }
        
        else if(this.array1.length===0){
            this.service3.getValidity('').subscribe((res)=>{
                
            })
        }
        })
    }
}


ngOnDestroy() {
    if (this.subscription1 && !this.subscription1.closed) {
      this.subscription1.unsubscribe();
    }
    if (this.subscription2 && !this.subscription2.closed) {
      this.subscription2.unsubscribe();
    }
    if (this.subscription3 && !this.subscription3.closed) {
      this.subscription3.unsubscribe();
    }
  }

Despite implementing subscription management within onDestroy, the issue persisted. It became evident that the nested function calls of B() inside A() were causing the problem.

My main objective is to ensure that function A completes its task of populating values in data and array1 before invoking function B. How can I achieve this efficiently without facing multiple subscription calls?

Answer №1

If you prefer not to subscribe, an alternative method is to utilize firstValueFrom (https://rxjs.dev/api/index/function/firstValueFrom). This function returns a Promise from an Observable, allowing you to directly await the promise which resolves only once.

import { firstValueFrom, map } from 'rxjs';

async ngOnInit() {
    const response = await firstValueFrom(A());
    B(response);
}
A() {
    return this.service1.getData().pipe(
        map((resp) => {
            return; //perform actions with the response
        })
    );
}

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

Despite being listed in the entry components, HelloComponent is not actually included in the NgModule

Check out my StackBlitz demo where I am experimenting with dynamically instantiating the HelloComponent using the ReflexiveInjector. The HelloComponent is added to the app modules entryComponents array. Despite this setup, I am still encountering the foll ...

Error with the `this` keyword in TypeScript - value is undefined

I'm encountering an issue with my AWS Lambda function written in TypeScript that calls functions from different classes. The problem is that I am receiving 'undefined' for the existingProducts variable, even though it functions correctly whe ...

Struggling with updating a spring boot entity table through angular, especially when incorporating new parameters in typescript

Within the BidPerContestController class, I have defined two controller functions related to spring boot: @PostMapping public void postBid(@RequestBody BidPerContest bid){ bidPerContestService.setBidPerContest(bid); } @PatchMa ...

View the material expansion panel by scrolling without turning off the animation

Whenever a MaterialExpansionPanel opens, I use the scrollIntoView method. opened(i) { setTimeout(() => this.panels.toArray()[i].nativeElement.scrollIntoView({ behavior: 'smooth' } )); } Although it works, if the animation ([@. ...

Ran into an issue while executing ng build --prod: The JavaScript heap has run out of memory

After executing ng build --prod, I encounter the error below. What steps can I take to resolve this issue? FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory ...

An error occurred in Angular2 when attempting to resolve a Promise: The type 'Promise<Hero[]>' is not compatible with the type 'Hero[]'

Recently updated. Currently, I am working through an Angular2 tutorial which can be found at this link Highlighted below is the code snippet for calling the HeroService from heroes.component.ts, Heroes.component.ts import { Component , OnInit } from ...

Receive a notification when the div element stops scrolling

I am attempting to replicate Android's expandable toolbar within an Angular component. My HTML code appears as follows: <div (scroll)="someScroll($event)"> <div class="toolbar"></div> <div class="body"></div> </d ...

What is the best way to eliminate duplicate files from an Angular input file?

Currently, I am working on a web application that includes a feature to upload files. For each file, there is a separate input field. The issue arises when a user selects a file from the same input field twice, resulting in two different files of the same ...

Utilizing TypeScript 3.1: Easier Array Indexing with Enums in Strict Mode

Enabling TypeScript "strict" mode with "noImplicitAny" causes this code to fail compilation. I am looking for guidance on how to properly declare and use Arrays indexed by Enum values. namespace CommandLineParser { enum States { sNoWhere, sSwitchValu ...

Submit numerous queries to verify the presence of a name and assign it to the name attribute

I have a collection of unique devices. As part of a process, I need to assign a default name to each device ("DeviceX" - where X is a sequential number), but some of the names may already be in use. To handle this, I must make a request to check ...

What is the significance of utilizing generic types as values within a generic class?

Why is the compiler giving an error for the following code T' only refers to a type, but is being used as a value here: class Factory<T> { create(TCreator: (new () => T)): T { return new TCreator(); } test(json: string) ...

Is it safe to remove npm packages that have been labeled as NOTUSED by npm-check without causing any issues

In the process of refactoring an Angular/Ionic project that I recently inherited, I decided to run a tool called npm-check. Much to my surprise, it detected several dependencies labeled as NOTUSED. The tool advised to "Check your code before removing as de ...

Is it recommended to employ cluster connection within my Redis client when utilizing Azure Redis Cluster?

It seems that the Azure documentation on clustering can be a bit confusing. According to the docs: Will my client application need any modifications to support clustering? Once clustering is activated, only database 0 will be accessible. If your client ...

Printing error stack that includes the source from the source map

I've been trying to take advantage of the native support for source maps in Node, but I'm having trouble getting them to work when printing errors to the console. Despite running node with --enable-source-maps and using the source-map-support pa ...

The parameter type '(req: Request, res: Response, next: NextFunction) => void' does not match the type of 'Application<Record<string, any>>'

I'm currently working on an Express project that utilizes TypeScript. I have set up controllers, routers, and implemented a method that encapsulates my controller logic within an error handler. While working in my router.ts file, I encountered an err ...

Is there a way for me to generate a custom subtype of Error that can be thrown?

I am attempting to create my own custom error in order to handle it differently when catching it. I want to be able to call if(instanceof DatabaseError) and execute my specific handling logic. export class DatabaseError extends Error { constructor(...a ...

Setting up Angular 2 for Highcharts: A Comprehensive Guide

Having trouble implementing a highchart component in my Angular 2 project after setting it up with the latest version. I've created a linechart component directory and tried to add the chart using the <line-chart></line-chart> tag in the H ...

Placing a blank object after every line within a TypeScript array

I'm currently working on creating an iterator using the .map() function, specifically in this way: const csv = this.invoices .map(data => ({ invoiceId: data.invoiceId, invoiceDate: data.invoiceDate, invoiceType: data.invoiceType, ...

Validate if a certain value exists within an array of data using NgIf

Is there a way to verify the existence of a value in an array of data? gjhg = [ id, name ] ...

After installation, the local development environment for Angular 2 consistently runs just once

After following the local setup instructions for Angular 2 on Windows 10 as outlined at https://angular.io/docs/ts/latest/guide/setup.html, the initial run of the development environment works perfectly with "npm install" and "npm start". However, upon clo ...