Angular 4+ ngOnDestroy () 서비스 중-Observable 제거


104

각도 응용 프로그램에서 우리는 ngOnDestroy()구성 요소 / 지시문에 대한 수명주기 후크를 가지고 있으며이 후크를 사용하여 관찰 가능 항목을 구독 취소합니다.

@injectable()서비스 에서 생성 된 Observable을 삭제 / 삭제하고 싶습니다 . ngOnDestroy()서비스에서도 사용할 수 있다는 글을 보았습니다 .

그러나 그것은 좋은 습관이며 그렇게하는 유일한 방법이며 언제 호출됩니까? 누군가 명확히하십시오.

답변:


120

OnDestroy 수명주기 후크는 공급자에서 사용할 수 있습니다. 문서에 따르면 :

지시문, 파이프 또는 서비스가 파괴 될 때 호출되는 수명주기 후크입니다.

다음은 예입니다 .

@Injectable()
class Service implements OnDestroy {
  ngOnDestroy() {
    console.log('Service destroy')
  }
}

@Component({
  selector: 'foo',
  template: `foo`,
  providers: [Service]
})
export class Foo implements OnDestroy {
  constructor(service: Service) {}

  ngOnDestroy() {
    console.log('foo destroy')
  }
}

@Component({
  selector: 'my-app',
  template: `<foo *ngIf="isFoo"></foo>`,
})
export class App {
  isFoo = true;

  constructor() {
    setTimeout(() => {
        this.isFoo = false;
    }, 1000)
  }
}

위의 코드 Service에서 Foo컴포넌트에 속하는 인스턴스가 있으므로이 인스턴스가 소멸 될 때 소멸 될 수 있습니다 Foo.

루트 인젝터에 속한 프로 바이더의 경우 이는 애플리케이션 파괴시 발생합니다. 이는 테스트에서와 같이 여러 부트 스트랩으로 메모리 누수를 방지하는 데 도움이됩니다.

부모 인젝터의 공급자가 자식 구성 요소에 구독되면 구성 요소가 파괴 될 때 파괴되지 않으며 구성 요소에서 구독을 취소하는 것은 구성 요소의 책임입니다 ngOnDestroy(다른 답변에서 설명).


아니 class Service implements OnDestroy? 그리고 당신은 서비스 모듈 수준에서 제공되는 경우이 호출 할 때 어떻게 생각하십니까
Shumail

1
implements OnDestroy아무 영향도 미치지 않지만 완전성을 위해 추가 할 수 있습니다. 모듈이 파괴되면 호출됩니다 appModule.destroy(). 이는 여러 앱 초기화에 유용 할 수 있습니다.
Estus Flask

1
서비스를 사용하는 모든 구성 요소에 대해 구독 취소가 필요합니까?
Ali Abbaszade

2
Plunker가 나를 위해 작동하지 않았으므로 여기 StackBlitz 버전의 예제가 있습니다. stackblitz.com/edit/angular-mggk9b
compuguru

1
나는 이것을 이해하는 데 약간의 어려움이 있었다. 하지만이 토론은 지역 서비스와 글로벌 서비스의 차이를 이해하는 데 도움이되었습니다. stackoverflow.com/questions/50056446/… "정리" 해야하는지 여부는 서비스 범위에 따라 달라집니다.
Jasmin

26

서비스에서 변수 만들기

subscriptions: Subscriptions[]=[];

각 구독을 다음과 같이 어레이에 푸시하십시오.

this.subscriptions.push(...)

dispose()방법 작성

dispose(){
this.subscriptions.forEach(subscription =>subscription.unsubscribe())

ngOnDestroy 중에 컴포넌트에서이 메소드를 호출하십시오.

ngOnDestroy(){
   this.service.dispose();
 }

당신의 답변에 감사드립니다. 이 ngOnDestroy가 언제 호출 될지 알 수 있습니까? ?
mperle

예, 지시문이나 구성 요소가 파괴되기 전에 정리 호출이라고 말합니다. 하지만 서비스에도 적용 가능한지 알고 싶습니다.
mperle aug

모듈이 언로드되면 서비스가 지워지지 않습니다
Aravind

2
라이프 사이클 후크는 적용되지 않습니다@injectables
Aravind

@Aravind들이 도입 할 때 잘 모르겠어요하지만 그들이 있습니다 .
Estus Flask

11

takeUntil(onDestroy$)pipable 연산자에 의해 활성화 된 이 패턴을 선호합니다 . 이 패턴이 더 간결하고 깔끔하며 OnDestroy라이프 사이클 후크 실행시 구독을 종료하려는 의도를 명확하게 전달하는 것이 좋습니다.

이 패턴은 주입 된 Observable을 구독하는 구성 요소뿐만 아니라 서비스에도 적용됩니다. 아래의 스켈레톤 코드는 패턴을 자체 서비스에 통합하기에 충분한 세부 정보를 제공해야합니다. InjectedService... 라는 서비스를 가져오고 있다고 상상해보십시오 .

import { InjectedService } from 'where/it/lives';
import { Injectable, OnDestroy } from '@angular/core';
import { Observable } from 'rxjs/Rx';
import { takeUntil } from 'rxjs/operators';
import { Subject } from 'rxjs/Subject';

@Injectable()
export class MyService implements OnDestroy {

  private onDestroy$ = new Subject<boolean>();

  constructor(
    private injectedService: InjectedService
  ) {
    // Subscribe to service, and automatically unsubscribe upon `ngOnDestroy`
    this.injectedService.observableThing().pipe(
      takeUntil(this.onDestroy$)
    ).subscribe(latestTask => {
      if (latestTask) {
        this.initializeDraftAllocations();
      }
    });
  }

  ngOnDestroy() {
    this.onDestroy$.next(true);
    this.onDestroy$.complete();
  }

구독 취소시기 / 방법에 대한 주제는 여기에서 광범위하게 다룹니다. Angular / RxJs 언제 구독 취소해야합니까?


5

명확히하기 위해-폐기 할 필요가 없으며 Observables구독 만 가능합니다.

다른 사람들이 이제 ngOnDestroy서비스와 함께 사용할 수 있다고 지적한 것 같습니다 . 링크 : https://angular.io/api/core/OnDestroy


1
당신은 그것을 더 자세히 설명해 수
라빈

2

토큰 사용시주의 사항

내 응용 프로그램을 가능한 모듈 식으로 만들려고 할 때 종종 공급자 토큰을 사용하여 구성 요소에 서비스를 제공합니다. 이것들은 다음과 같은 ngOnDestroy메소드를 얻지 못하는 것 같습니다 :-(

예.

export const PAYMENTPANEL_SERVICE = new InjectionToken<PaymentPanelService>('PAYMENTPANEL_SERVICE');

구성 요소에 공급자 섹션이있는 경우 :

 {
     provide: PAYMENTPANEL_SERVICE,
     useExisting: ShopPaymentPanelService
 }

My ShopPaymentPanelService에는 ngOnDestroy구성 요소가 삭제 될 때 호출되는 메서드 가 없습니다 . 나는 이것을 어려운 방법으로 발견했다!

해결 방법은와 함께 서비스를 제공하는 것입니다 useExisting.

[
   ShopPaymentPanelService,

   {
       provide: PAYMENTPANEL_SERVICE,
       useExisting: ShopPaymentPanelService
   }
]

내가 이것을 할 때 ngOnDispose예상대로 호출되었습니다.

이것이 버그인지 아닌지 확실하지 않지만 매우 예상치 못한 것입니다.


좋은 힌트! 내 경우에는 왜 작동하지 않는지 궁금합니다 (구체적인 구현을 위해 추상 클래스 인터페이스를 토큰으로 사용했습니다).
Andrei Sinitson
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.