How to implement ngOnDestroy() correctly in Angular?

纵然是瞬间 提交于 2020-05-23 09:12:10

问题


I have a child component with a timer, every 2 second I send api call to the server. I need to do this call as long as the user is on the page even if he/she going to a wedding and leave the page (the parent compoent window) open.

Here is some code from my component:

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

And here is the destroy method:

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

I simply click on the menu to different component and see that the calls to the sever is still happening. I've tried even to close the window (the tab from chrome browser), still the calls to server remains.

Any idea why the ngOnDestroy doesn't get called ?

UPDATE I'm using "rxjs": "^5.5.12",

from 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"

回答1:


Hmm.. You can try using RxJS's takeUntil operator instead.

First and foremost, you import takeUntil and Subject into your component.

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

Next,

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

And then,

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

Do take note that takeUntil must be the last operator on your pipe() to prevent any observables from 'leaking' out.

And on your ngOnDestroy,

ngOnDestroy() {
  this.unsubscribe.next();
  this.unsubscribe.complete();
}



回答2:


Well, observables are asynchronous patterns. They are based on push rather than pull strategy i.e. when they got data, they push data to the subscriber. Now, you must take caution while working with them as they continue to push data even when the component destroys. You need to explicitly unsubscribe from the observable. In ngOnDestroy() lifecycle hook you need this piece of code too.

this.myTimer.unsubscribe()

And that's it, you will not get more data. Alternatively, you can use takeWhile() or takeUntil() approach. Have a look- https://brianflove.com/2016/12/11/anguar-2-unsubscribe-observables/



来源:https://stackoverflow.com/questions/56672547/how-to-implement-ngondestroy-correctly-in-angular

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