Stop a continuous function being called once I leave the component in Angular

二次信任 提交于 2020-03-24 09:46:05

问题


I am building an app using Angular. As part of it, I am making an API call every 1 min for continuous data. My code looks like.

ngOnInit() {
    this.getRealTimeData();
  }

  intervalId : any

  getRealTimeData() {
    this.getChillerApiData()
    clearInterval(this.intervalId);
    this.intervalId = setInterval(() => {
      this.getChillerApiData();
    }, 1000);
  }

  getChillerApiData() {
    this.api.getFirstChillerData()
      .subscribe((first_data:any) => {
        this.first_api_data = first_data;
        console.log(this.first_api_data)
        this.putPrimaryPumpData();
      });
  }

I am getting data every 1 min or whatever time interval I mention. But what is happening is when I leave the component and go on to another component, still I see API calls made regularly at specified interval (I can see the console logs). How do I stop that from happening? I mean once I leave this component API calls should also stop.


回答1:


First of all there are so many things wrong here.

You call an subscribition and it's not unsubscribed. You want to unsubscribe the subscribition and you want to clear the interval. If the subscribition is not cleared it will keep getting info and keep repeating it. So putPrimaryPumpData will be called everytime the subscription is fired. Which can conclude in multiple running at the same time.

Do something like:

let sub = this.api.getFirstChillerData()
  .subscribe((first_data:any) => {
    sub.unsubscribe();
    this.first_api_data = first_data;
    console.log(this.first_api_data)
    this.putPrimaryPumpData();
  });

Now this will not create like 100 of 1000 of loops. Second you can use ngOnDestroy like:

ngOnDestroy() {
  clearInterval(this.intervalId);
}



回答2:


You can clear up your component in ngOnDestroy. This function is called by Angular when the component removed from the DOM.

You could clear the interval in ngOnDestroy, but in your case you're probably better off performing the interval in RxJS, which your existing call can be part of.

// other imports here
import { interval } from 'rxjs';
import { takeUntil, switchMap } from 'rxjs/operators';

// @Component decorator here
export class MyComponent implements OnInit, OnDestroy {

  // TODO: add constructor

  private destroyed: Subject<void> = new Subject<void>();

  ngOnInit() {
    // create an rxjs interval every 1000ms
    // or you could use timer(0, 1000) to start immediately
    interval(1000).pipe(
      // stop the interval whenever this.destroyed is called
      takeUntil(this.destroyed),
      // now make the api request
      switchMap(() => this.api.getFirstChillerData())
    ).subscribe(data => {
      this.first_api_data = data;
      this.putPrimaryPumpData();
    });
  }

  ngOnDestroy() {
    // called when the component is removed from the DOM. 
    // cancel the interval and tidy up
    this.destroyed.next();
    this.destroyed.complete();
  }
}




回答3:


Exactly for cases like this angular provides the OnDestroy life cycle event. You can hook to this event the clear the interval.

like this:

intervalId : any

ngOnDestory() {
 clearInterval(this.intervalId);
}



回答4:


Use OnDestroy() lifecycle hook.

import { Component, OnInit, OnDestroy } from '@angular/core';
import { Subscription } from 'rxjs/Subscription';

export class AppComponent implements OnInit, OnDestroy {
  private intervalId: any
  private chillerDataSubscription: Subscription;

  constructor() { }

  ngOnInit() {
    this.getRealTimeData();
  }

  getRealTimeData() {
    this.getChillerApiData()
    clearInterval(this.intervalId);
    this.intervalId = setInterval(() => {
      this.getChillerApiData();
    }, 1000);
  }

  getChillerApiData() {
    if (this.chillerDataSubscription) {
      this.chillerDataSubscription.unsubscribe();
    }
    this.chillerDataSubscription = this.api.getFirstChillerData()
      .subscribe((first_data:any) => {
        this.first_api_data = first_data;
        console.log(this.first_api_data)
        this.putPrimaryPumpData();
      });
  }

  ngOnDestroy() {
    if (this.intervalId) {
      clearInterval(this.intervalId);
    }
    if (this.chillerDataSubscription) {
      this.chillerDataSubscription.unsubscribe();
    }
  }
}

See here for more details on lifecycle hooks.

I assume you are making a HTTP request inside your api service. In that case, notice the chillerDataSubscription inside the getChillerApiData() function. It makes sure any outstanding requests are unsubscribed before making a new request. It prevents accumulation of too many requests.



来源:https://stackoverflow.com/questions/60389797/stop-a-continuous-function-being-called-once-i-leave-the-component-in-angular

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!