Как правильно реализовать ngOnDestroy () в Angular 5? - PullRequest
3 голосов
/ 19 июня 2019

У меня есть дочерний компонент с таймером, каждые 2 секунды я отправляю вызов API на сервер.Мне нужно сделать этот вызов, пока пользователь находится на странице, даже если он / она собирается на свадьбу и оставляет страницу (окно родительского компонента) открытой.

Вот код из моего компонента:

this.myTimer = Observable.timer(1, 2000);
    this.myTimer
        .mergeMapTo(this.myService.doSomeWork(this.myId))
        .subscribe((data) => {
                this.myData = data;                
            }, (errRes)=>{
            console.log(errRes);
        });

А вот метод уничтожения:

  ngOnDestroy(): void {
    this.myTimer.complete();
  }

Я просто нажимаю на меню для другого компонента и вижу, что обращения к серверу все еще происходят.Я даже пытался закрыть окно (вкладка из браузера Chrome), но звонки на сервер остаются.

Есть идеи, почему не вызывается ngOnDestroy?

ОБНОВЛЕНИЕ Я использую "rxjs": "^ 5.5.12",

из package.json:

"dependencies": {
    "@angular/animations": "^5.2.11",
    "@angular/common": "^5.2.11",
    "@angular/compiler": "^5.2.11",
    "@angular/core": "^5.2.11",
    "@angular/forms": "^5.2.11",
    "@angular/http": "^5.2.11",
    "@angular/platform-browser": "^5.2.11",
    "@angular/platform-browser-dynamic": "^5.2.11",
    "@angular/router": "^5.2.11",
    "angular-file-saver": "^1.1.3",
    "angular-webstorage-service": "^1.0.2",
    "core-js": "^2.6.9",
    "file-saver": "^2.0.2",
    "jquery": "^3.4.1",
    "moment": "^2.24.0",
    "ngx-bootstrap": "^2.0.5",
    "ngx-select-dropdown": "^1.0.1",
    "ngx-select-ex": "^3.6.10",
    "ngx-select-options": "^1.0.5",
    "rxjs": "^5.5.12",
    "web-animations-js": "^2.3.1",
    "zone.js": "^0.8.29"

Ответы [ 2 ]

3 голосов
/ 19 июня 2019

Хмм .. Вместо этого вы можете попробовать использовать оператор RxJS takeUntil .

Прежде всего, вы импортируете takeUntil и Subject в свой компонент.

import { takeUntil, mergeMap } from 'rxjs/operators';
import { Subject } from 'rxjs/Subject'

Далее,

unsubscribe: Subject<void> = new Subject();

А затем

this.myTimer
  .pipe(
    mergeMap(this.myService.doSomeWork(this.myId)),
    takeUntil(this.unsubscribe)
  ).subscribe((data) => {
    this.myData = data;                
  }, (errRes)=>{
    console.log(errRes);
  });

Обратите внимание, что takeUntil должен быть последним оператором на вашем pipe(), чтобы предотвратить утечку любых наблюдаемых.

И на вашем ngOnDestroy,

ngOnDestroy() {
  this.unsubscribe.next();
  this.unsubscribe.complete();
}
3 голосов
/ 19 июня 2019

Ну, наблюдаемые - это асинхронные шаблоны. Они основаны на стратегии push, а не pull, то есть когда они получают данные, они передают данные подписчику. Теперь вы должны соблюдать осторожность при работе с ними, поскольку они продолжают отправлять данные, даже когда компонент разрушается. Вам нужно явно отписаться от наблюдаемого. В хуке жизненного цикла ngOnDestroy () вам также нужен этот фрагмент кода.

this.myTimer.unsubscribe()

И это все, вы не получите больше данных. В качестве альтернативы вы можете использовать подход takeWhile () или takeUntil (). Посмотри- https://brianflove.com/2016/12/11/anguar-2-unsubscribe-observables/

...