질문 : Angular / RxJs`Subscription` 구독 취소는 언제해야합니까?
Subscription
인스턴스를 저장하고 unsubscribe()
호출해야하는시기와 무시할 수있는시기는 언제입니까?
모든 구독을 저장하면 구성 요소 코드가 엉망이됩니다.
HTTP 클라이언트 가이드 는 다음과 같은 구독을 무시합니다.
getHeroes() {
this.heroService.getHeroes()
.subscribe(
heroes => this.heroes = heroes,
error => this.errorMessage = <any>error);
}
동시에 Route & Navigation Guide 는 다음과 같이 말합니다.
결국 우리는 다른 곳으로 이동할 것입니다. 라우터는 DOM에서이 구성 요소를 제거하고 파괴합니다. 그런 일이 일어나기 전에 우리는 스스로 청소해야합니다. 특히 Angular가 컴포넌트를 파괴하기 전에 구독을 취소해야합니다. 그렇게하지 않으면 메모리 누수가 발생할 수 있습니다.
ngOnDestroy
메서드에서 Observable
구독을 취소합니다.
private sub: any;
ngOnInit() {
this.sub = this.route.params.subscribe(params => {
let id = +params['id']; // (+) converts string 'id' to a number
this.service.getHero(id).then(hero => this.hero = hero);
});
}
ngOnDestroy() {
this.sub.unsubscribe();
}
답변
--- 편집 4 - 추가 리소스 (2018/09/01)
Angular 의 Adventures 최근 에피소드에서 Ben Lesh와 Ward Bell은 구성 요소의 구독 취소 방법 /시기에 대한 문제를 논의합니다. 토론은 약 1:05:30에 시작됩니다.
Ward는 right now there's an awful takeUntil dance that takes a lot of machinery
언급하고 Shai Reznik은 Angular handles some of the subscriptions like http and routing
한다고 언급합니다.
이에 대한 응답으로 Ben은 Observable이 Angular 구성 요소 수명주기 이벤트에 연결될 수 있도록 현재 논의 중이라고 언급하고 Ward는 구성 요소 내부 상태로 유지되는 Observable을 완료해야하는시기를 알 수있는 방법으로 구성 요소가 구독 할 수있는 수명주기 이벤트의 Observable을 제안합니다.
즉, 현재 대부분 솔루션이 필요하므로 여기에 다른 리소스가 있습니다.
takeUntil()
패턴에 대한 권장 사항과이를 시행하는 데 도움이되는 tslint 규칙입니다. https://ncjamieson.com/avoiding-takeuntil-leaks/this
)를 매개 변수로 사용하고ngOnDestroy
동안 자동으로 구독을 취소하는 Observable 연산자를 노출하는 경량 npm 패키지입니다. https://github.com/NetanelBasal/ngx-take-until-destroy- AOT 빌드를 수행하지 않는 경우 약간 더 나은 인체 공학적 위의 또 다른 변형입니다 (그러나 우리 모두 지금 AOT를 수행해야합니다). https://github.com/smnbbrv/ngx-rx-collector
- 비동기 파이프처럼 작동하지만 템플릿에 포함 된 뷰를 생성하는 사용자 지정 지시문
*ngSubscribe
는 템플릿 전체에서 'unwrapped'값을 참조 할 수 있습니다. https://netbasal.com/diy-subscription-handling-directive-in-angular-c8f6e762697f
Nicholas의 블로그에 대한 의견에서 takeUntil()
을 과도하게 사용하면 구성 요소가 너무 많은 작업을 수행하고 기존 구성 요소를 Feature 및 Presentational 구성 요소로 분리하는 것을 고려해야한다는 신호일 수 있다고 언급했습니다. 그런 다음 | async
에 기능 성분으로부터 관찰 Input
구독 정보가 필요 없음을 의미 어딘가에 표상 성분의. 여기 에서이 접근 방식에 대해 자세히 알아보십시오.
--- 편집 3 - '공식' 솔루션 (2017/04/09)
나는 NGConf에서이 질문에 대해 Ward Bell과 이야기를 나눴습니다. (저는 그가 옳다고 말한이 대답을 보여주었습니다) Angular의 문서 팀이이 질문에 대해 게시되지 않은 해결책을 가지고 있다고 말했습니다. ). 그는 또한 다가오는 공식 권장 사항으로 내 SO 답변을 업데이트 할 수 있다고 말했습니다.
앞으로 우리 모두가 사용해야 할 해결책은 private ngUnsubscribe = new Subject();
.subscribe()
가 클래스 코드 내 Observable
호출하는 모든 구성 요소에 필드를 추가합니다.
그런 다음 this.ngUnsubscribe.next(); this.ngUnsubscribe.complete();
ngOnDestroy()
메서드에서.
비밀 소스 ( @metamaker에서 이미 언급했듯이)는 각 .subscribe()
takeUntil(this.ngUnsubscribe)
를 호출하여 구성 요소가 파괴 될 때 모든 구독이 정리되도록 보장하는 것입니다.
예:
import { Component, OnDestroy, OnInit } from '@angular/core';
// RxJs 6.x+ import paths
import { filter, startWith, takeUntil } from 'rxjs/operators';
import { Subject } from 'rxjs';
import { BookService } from '../books.service';
@Component({
selector: 'app-books',
templateUrl: './books.component.html'
})
export class BooksComponent implements OnDestroy, OnInit {
private ngUnsubscribe = new Subject();
constructor(private booksService: BookService) { }
ngOnInit() {
this.booksService.getBooks()
.pipe(
startWith([]),
filter(books => books.length > 0),
takeUntil(this.ngUnsubscribe)
)
.subscribe(books => console.log(books));
this.booksService.getArchivedBooks()
.pipe(takeUntil(this.ngUnsubscribe))
.subscribe(archivedBooks => console.log(archivedBooks));
}
ngOnDestroy() {
this.ngUnsubscribe.next();
this.ngUnsubscribe.complete();
}
}
참고 : 연산자 체인에서 중간 관측 값으로 누출을 방지 takeUntil
연산자를 마지막 연산자로 추가하는 것이 중요합니다.
--- 편집 2 (2016/12/28)
소스 5
Angular 튜토리얼, 라우팅 장은 이제 다음과 같이 설명합니다. "라우터는 제공하는 Observable을 관리하고 구독을 지역화합니다. 구독은 구성 요소가 파괴 될 때 정리되어 메모리 누수를 방지하므로 구독을 취소 할 필요가 없습니다. 경로 매개 변수 Observable. " -Mark Rajcok
다음은 Ward Bell이이 모든 작업에 대한 설명이 진행 중이라고 언급 한 Router Observable에 관한 Angular 문서의 Github 문제에 대한 토론입니다.
--- 편집 1
소스 4
NgEurope의이 비디오에서 Rob Wormald는 또한 Router Observables에서 구독을 취소 할 필요가 없다고 말합니다. 또한 2016 년 11 월부터이 동영상에서 http
서비스와 ActivatedRoute.params
를 언급했습니다.
--- 원본 답변
TLDR :
이 질문에는 (2) 종류의 Observables
유한 값과 무한 값이 있습니다.
http
Observables
은 유한 (1) 값을 event listener
Observables
은 무한 값을 생성합니다.
subscribe
호출하는 경우 (비동기 파이프를 사용하지 않음), 무한 Observables
에서 unsubscribe
.
유한 한 것에 대해 걱정하지 마십시오. RxJs
가 처리합니다.
소스 1
나는 각도의 Gitter에서 롭 Wormald에서 답변을 추적 여기 .
그는 말합니다 (명확성을 위해 재구성되었으며 강조는 내 것입니다)
단일 값 시퀀스 (예 : http 요청) 인 경우 수동 정리가 필요하지 않습니다 (컨트롤러에서 수동으로 구독한다고 가정).
나는 "만약 완료되는 시퀀스 인 경우"라고 말해야합니다 (단일 값 시퀀스, a la http가 하나입니다).
무한 시퀀스 인 경우 비동기 파이프가 수행하는 작업을 구독 취소해야합니다.
또한 그는 Observables에 대한 이 유튜브 비디오 they clean up after themselves
complete
Observable의 맥락에서 (Promises처럼, 항상 1 개의 값을 생성하고 끝나기 때문에 항상 완료됩니다. 우리는 Promises에서 구독 취소에 대해 걱정하지 않았습니다. xhr
이벤트 리스너를 정리했는지 확인하십시오.
소스 2
또한 Angular 2 에 대한 Rangle 가이드에서 다음과 같이 읽습니다.
대부분의 경우 우리가 일찍 취소하거나 Observable이 구독보다 수명이 더 긴 경우가 아니면 unsubscribe 메서드를 명시 적으로 호출 할 필요가 없습니다. Observable 연산자의 기본 동작은 .complete () 또는 .error () 메시지가 게시되는 즉시 구독을 삭제하는 것입니다. RxJS는 대부분의 경우 "불만 잊으면"방식으로 사용되도록 설계되었습니다.
our Observable has a longer lifespan than our subscription
경우는 언제입니까?
Observable
완료되기 전에 (또는 '오래'가 아닌) 파괴 된 컴포넌트 내부에 구독이 생성 될 때 적용됩니다.
http
요청이나 10 개의 값을 방출하는 옵저버 블을 http
요청이 반환되거나 10 개의 값이 방출되기 전에 컴포넌트가 파괴되는 경우이를 의미로 읽었습니다. 여전히 괜찮습니다!
요청이 반환되거나 10 번째 값이 최종적으로 방출되면 Observable
이 완료되고 모든 리소스가 정리됩니다.
소스 3
우리가 보면 이 예제 같은 Rangle 가이드에서 우리가 볼 수있는 Subscription
에 route.params
필요합니까 unsubscribe()
그 때 우리가 모르기 때문에 params
변경 (새로운 가치를 방출) 중지됩니다.
구성 요소는 경로 매개 변수가 여전히 변경 될 가능성이 있고 (앱이 종료 될 때까지 기술적으로 변경 될 수 있음) 이동하여 제거 할 수 있으며 completion
가 없었기 때문에 구독에 할당 된 리소스가 여전히 할당됩니다.
출처 : https://stackoverflow.com/questions/38008334/angular-rxjs-when-should-i-unsubscribe-from-subscription
'개발관련 > other' 카테고리의 다른 글
AngularJS : $ scope. $ apply () 호출시 $digest already in progress 오류 해결방법 (0) | 2021.10.01 |
---|---|
GUID와 UUID간에 차이점 (0) | 2021.10.01 |
오래되고 사용되지 않는 Docker 이미지를 제거하는 방법 (0) | 2021.09.29 |
Haskell은 현실 세계에서 무엇에 사용되는가? (0) | 2021.09.28 |
deep copy와 shallow copy의 차이점 (0) | 2021.09.28 |