Search code examples
angularinfinite-loop

How to prevent an infinite loop call while assigning element a value to a service in Angular?


I have encountered a problem assigning an element's value to a service. In this scenario, the value of the component is populated with the result of the response from the server. But this calling service falls in a loop and the site ultimately crashes.

This is my component.cs code:

count = -1;

constructor(
    private formBuilder: FormBuilder,
    private referralService: ReferralService
) { }
 
getCount() {
    this.referralService
        .getAll()
        .pipe(first())
        .subscribe((response) => {
            this.count = response.data;
        });
            
    return this.count;
}

And this is my component.html:

<div class="alert alert-success" role="alert" style="width: 100%">
    <div class="b" style="display: flex">
        You have
        <div style="padding-left: 5px; padding-right: 5px">{{getCount()}}</div>
        counts right now
    </div>
</div>

Because of unknown reasons this getCount() is called countless times.


Solution

  • Subscribe Once

    In this line:

    <div style="padding-left: 5px; padding-right: 5px">{{getCount()}}</div>
    

    You keep subscribing to some service.

    Try this instead:

    <div style="padding-left: 5px; padding-right: 5px">{{ count }}</div>
    

    You should call getCount() just once. It doesn't need a return value. And you might also want to unsubscribe:

    sub: Subscription;
    
    ngOnInit() {
        this.sub = this.referralService
            .getAll()
            .pipe(first())
            .subscribe((response) => {
                this.count = response.data;
            });
    }
    
    ngOnDestroy() {
        this.sub.unsubscribe()
    }
    

    There are other ways to unsubscribe, but that would be outside the scope of this question.

    Async Pipe

    Or you prevent having to subscribe by using the async pipe.

    That would look something like this in your script:

    count$ = this.referralService
            .getAll()
            .pipe(first());
    

    And in your template:

    <div style="padding-left: 5px; padding-right: 5px">{{ count$ | async }}</div>