Остановите непрерывную функцию, вызываемую, когда я оставляю компонент в Angular - PullRequest
1 голос
/ 25 февраля 2020

Я создаю приложение, используя Angular. Как часть этого, я делаю вызов API каждые 1 минуту для непрерывных данных. Мой код выглядит следующим образом.

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();
      });
  }

Я получаю данные каждые 1 минуту или любой другой интервал времени, который я упоминаю. Но происходит то, что когда я оставляю компонент и go на другом компоненте, я по-прежнему вижу регулярные вызовы API с заданным интервалом (я вижу журналы консоли). Как мне остановить это? Я имею в виду, как только я покину этот компонент, вызовы API также должны прекратиться.

Ответы [ 4 ]

1 голос
/ 25 февраля 2020

Вы можете очистить свой компонент в ngOnDestroy. Эта функция вызывается Angular, когда компонент удален из DOM.

Вы можете очистить интервал в ngOnDestroy, но в вашем случае вам лучше выполнить интервал в Rx JS , частью которого может быть ваш существующий вызов.

// 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();
  }
}

1 голос
/ 25 февраля 2020

Именно для таких случаев angular предоставляет событие жизненного цикла OnDestroy. Вы можете подключиться к этому событию, чтобы очистить интервал.

вот так:

intervalId : any

ngOnDestory() {
 clearInterval(this.intervalId);
}
1 голос
/ 25 февраля 2020

Используйте OnDestroy() крюк жизненного цикла.

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();
    }
  }
}

См. здесь для более подробной информации о крюках жизненного цикла.

Я предполагаю, что вы сделать HTTP-запрос внутри вашего API-сервиса. В этом случае обратите внимание на chillerDataSubscription внутри функции getChillerApiData (). Он гарантирует, что все невыполненные запросы отписываются, прежде чем делать новый запрос. Это предотвращает накопление слишком большого количества запросов.

1 голос
/ 25 февраля 2020

Во-первых, здесь так много всего неправильного.

Вы звоните по подписке, и она не отписывается. Вы хотите отменить подписку, и вы хотите очистить интервал. Если подписка не очищена, она продолжит получать информацию и будет повторять ее. Таким образом, putPrimaryPumpData будет вызываться при каждом запуске подписки. Который может завершиться при многократном запуске одновременно.

Сделайте что-то вроде:

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();
  });

Теперь это не будет создавать как 100 из 1000 циклов. Во-вторых, вы можете использовать ngOnDestroy как:

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