Http 메서드에서 생성된 관찰 가능 항목의 구독을 취소할 필요가 있습니까?
메모리 누수를 방지하기 위해 Angular 2 http 통화의 구독을 취소해야 합니까?
fetchFilm(index) {
var sub = this._http.get(`http://example.com`)
.map(result => result.json())
.map(json => {
dispatch(this.receiveFilm(json));
})
.subscribe(e=>sub.unsubscribe());
...
그래서 답은 '아니오'입니다. Ng2
스스로 청소할 겁니다
Angular의 Http XHR 백엔드 소스의 Http 서비스 소스:
운영 방식에 주목하십시오.complete()
결과를 얻은 후에이것은 실제로 완료 시 구독을 취소한다는 것을 의미합니다.그래서 당신은 그것을 직접 할 필요가 없습니다.
다음은 검증할 테스트입니다.
fetchFilms() {
return (dispatch) => {
dispatch(this.requestFilms());
let observer = this._http.get(`${BASE_URL}`)
.map(result => result.json())
.map(json => {
dispatch(this.receiveFilms(json.results));
dispatch(this.receiveNumberOfFilms(json.count));
console.log("2 isUnsubscribed",observer.isUnsubscribed);
window.setTimeout(() => {
console.log("3 isUnsubscribed",observer.isUnsubscribed);
},10);
})
.subscribe();
console.log("1 isUnsubscribed",observer.isUnsubscribed);
};
}
예상대로 결과를 얻고 관측 가능한 연산자로 완료한 후에는 항상 자동으로 구독이 취소되는 것을 확인할 수 있습니다.이는 시간 초과(#3)에 발생하므로 모든 작업이 완료되고 완료되면 관찰 가능한 항목의 상태를 확인할 수 있습니다.
그리고 그 결과는
따라서 누출이 발생하지 않습니다.Ng2
자동 구독 취소!
말씀해 주셔서 감사합니다. 것이.Observable
는 로분됩니다로 됩니다.finite
에반여와는 infinite
Observable
는 DOM 즉, DOM 처럼 무한한 데이터 스트림을 방출할 수 .click
예를 들어 듣는 사람.
감사합니다, @rubyboy 이에 대한 도움을 주셔서.
당신들은 무슨 말을 하고 있는 겁니까!!!
좋아요, 그럼 관찰할 수 있는 것에서 구독을 취소해야 하는 두 가지 이유가 있습니다.아무도 매우 중요한 두 번째 이유에 대해 많이 말하는 것 같지 않습니다!
- 리소스를 정리합니다.다른 사람들이 말했듯이, 이것은 HTTP 관찰 가능한 문제에 대해 무시할 수 있는 문제입니다.저절로 깨끗해질 거예요.
- .
subscribe
핸들러를 실행할 수 없습니다.
HTTP를 관찰할 수 있는 경우 구독을 취소하면 브라우저의 기본 요청이 취소됩니다(네트워크 패널에 빨간색으로 '취소됨'이 표시됨).즉, 응답을 다운로드하거나 구문 분석하는 데 시간이 낭비되지 않습니다.하지만 그것은 사실 아래의 제 요점에 대한 부차적인 것입니다.
2번의 관련성은 구독 처리기가 수행하는 작업에 따라 달라집니다.
만약 당신이
subscribe()
핸들러 함수는 어떤 호출이든 닫히거나 처리된 경우 원하지 않는 부작용을 가지고 있으며, 실행되지 않도록 하려면 구독을 취소(또는 조건부 논리를 추가)해야 합니다.
몇 가지 경우를 생각해 보십시오.
로그인 양식.사용자 이름과 암호를 입력하고 '로그인'을 클릭합니다.서버 속도가 느려서 이스케이프를 눌러 대화상자를 닫으면 어떻게 됩니까?아마도 로그인하지 않았다고 가정하겠지만, 탈출을 누른 후 http 요청이 돌아왔다면, 당신은 여전히 당신이 가지고 있는 어떤 논리도 실행할 것입니다.이로 인해 계정 페이지로 리디렉션되거나 원하지 않는 로그인 쿠키 또는 토큰 변수가 설정될 수 있습니다.사용자가 예상한 것과 다를 수 있습니다.
'전자 메일 보내기' 양식입니다.
에 약에만.subscribe
'는 ' 메일이, 하거나, 항목에 않는 동작을 얻을 수 'sendEmail'의 'Email sent'는 메션을거나하나이거이트의하거동있수발않다킬시니작을생습원는예치나외여하도시고려하스액항세에목모든페로지제된다른이삭동리니애들핸는러▁handler▁for▁',▁is▁does'▁anything있발▁like
또한 다음을 가정하지 않도록 주의하십시오.unsubscribe()
하다'는입니다.유연'을 의미합니다. 메시지가 비행 중인 메시지입니다.unsubscribe()
서버에 이미 도달한 경우 HTTP 요청을 취소하지 않습니다.사용자에게 돌아오는 응답만 취소됩니다.그리고 이메일은 아마 보내질 것입니다.
UI 구성 요소 내에서 직접 전자 메일을 보내는 구독을 만든 경우에는 구독을 취소하고 싶지만, UI가 아닌 중앙 서비스에서 전자 메일을 보내는 경우에는 구독을 취소할 필요가 없습니다.
- 파괴/폐쇄되는 Angular 구성 요소입니다. 실행 중인 http 은 등을취지않한는실현중행모인든다재니에서 구독을 한 입니다.
onDestroy()
결과가 사소한지 여부는 구독 처리기에서 수행하는 작업에 따라 달라집니다.더 이상 존재하지 않는 것을 업데이트하려고 하면 오류가 발생할 수 있습니다.
구성 요소가 삭제된 경우 원하는 작업이 있을 수도 있고 그렇지 않은 작업이 있을 수도 있습니다.예를 들어, 보낸 전자 메일에 대해 '쉿' 소리가 날 수 있습니다.구성 요소가 닫혀 있는 경우에도 이 기능이 재생되기를 원할 수 있지만 구성 요소에서 애니메이션을 실행하려고 하면 실패합니다.이 경우 구독 내부의 추가 조건부 논리가 해결책이 될 것이며, 관찰 가능한 http를 구독 취소하지 않을 것입니다.
따라서 실제 질문에 대한 답변으로 메모리 누수를 방지하기 위해 이 작업을 수행할 필요가 없습니다.그러나 실행 중인 코드로 인해 예외가 발생하거나 응용 프로그램 상태가 손상될 수 있는 원치 않는 부작용이 발생하지 않도록 이 작업을 수행해야 합니다.
팁: 더Subscription
을 합니다.closed
고급 사례에서 유용할 수 있는 부울 속성입니다.HTTP의 경우 완료 시 설정됩니다.에서는 Angular(으)로 할 수 ._isDestroyed
의 ngDestroy
는 귀하의 할 수 .subscribe
핸들러
2:하는 경우 팁 2: 여 구 을 처 하 는 리 독 을 다 있 니 습 수 들 만 혹 드 러 애 우 경 ▁an 다 ▁tip ▁2 팁 니 ▁create 습 있 ▁multiple : ions ▁you ▁subscript ▁can ▁if - : ▁2new Subscription()
와 적어와add(...)
다른 모든 구독 - 기본 구독에서 구독을 취소하면 추가된 모든 구독도 구독을 취소합니다.
모든 네트워크 속도에서 결정론적 동작을 수행하려면 구독 취소가 필수입니다.
구성 요소 A가 탭에서 렌더링된다고 가정합니다. 버튼을 클릭하면 'GET' 요청이 전송됩니다.응답이 돌아오는 데 200ms가 걸립니다.따라서 언제든지 탭을 닫아도 안전합니다. 기계가 사용자보다 빠르며 http 응답이 처리되고 탭이 닫히고 구성 요소 A가 파괴되기 전에 완료됩니다.
매우 느린 네트워크에서는 어떻습니까?버튼을 클릭하면 'GET' 요청이 응답을 수신하는 데 10초가 걸리지만, 5초가 지나면 탭을 닫기로 결정합니다.그러면 나중에 가비지 수집될 구성 요소 A가 파괴됩니다.잠시만요! 구독을 취소하지 않았습니다. 이제 5초 후에 응답이 반환되고 파괴된 구성 요소의 논리가 실행됩니다.이제 그 처형이 고려되고 있습니다.out-of-context
매우 낮은 성능과 데이터/상태 손상을 비롯한 여러 가지 결과를 초래할 수 있습니다.
가장 좋은 방법은 다음과 방법을 사용하는 것입니다.takeUntil()
구성 요소가 파괴되면 http 통화 구독을 취소합니다.
참고:
- RxJS는 각도에 따라 다릅니다.
- 각
async
템플릿에 사용되는 파이프 자동 파기 시 구독 취소 - 두 번 이상 구독을 취소하면 추가적인 부작용을 제외하고는 부정적인 부작용이 없습니다.
no-op
통화
import { Component, OnInit, OnDestroy } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
interface User {
id: string;
name: string;
age: number;
}
@Component({
selector: 'app-foobar',
templateUrl: './foobar.component.html',
styleUrls: ['./foobar.component.scss'],
})
export class FoobarComponent implements OnInit, OnDestroy {
private user: User = null;
private destroy$ = new Subject();
constructor(private http: HttpClient) {}
ngOnInit() {
this.http
.get<User>('api/user/id')
.pipe(takeUntil(this.destroy$))
.subscribe(user => {
this.user = user;
});
}
ngOnDestroy(): void {
this.destroy$.next(); // trigger the unsubscribe
this.destroy$.complete(); // finalize & clean up the subject stream
}
}
에 unsubscribe
인데, 이 는 HTTP 요청을 입니다.abort
기본 XHR 개체에 하나씩 저장하고 로드 및 오류 이벤트에서 수신기를 제거합니다.
// From the XHRConnection class
return () => {
_xhr.removeEventListener('load', onLoad);
_xhr.removeEventListener('error', onError);
_xhr.abort();
};
그렇긴 하지만,unsubscribe
수신기 제거... 한 의 요청에;-) ㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅠ
도움이 되길 바래, 티에리
잠시 테스트한 후 HttpClient의 설명서와 소스 코드를 읽습니다.
HttpClient:
https://github.com/angular/angular/blob/master/packages/common/http/src/client.ts
HttpXhrBackend :
https://github.com/angular/angular/blob/master/packages/common/http/src/xhr.ts
HttpClientModule
https://indepth.dev/messages-the-messages 클라이언트 모듈-in-messages/
앵글 대학교: https://blog.angular-university.io/angular-http/
다음과 같은 특정 유형의 관찰 가능한 스트림은 단일 값 스트림입니다.HTTP 요청이 성공적인 경우 이러한 관찰 가능한 값은 하나만 내보내고 완료됩니다.
구독을 취소하려면 "do i need"의 전체 문제에 대한 답은 무엇입니까?
상황에 따라 다릅니다.Http call Memory leaks는 문제가 되지 않습니다.문제는 콜백 기능의 논리입니다.
예: 라우팅 또는 로그인.
통화가 로그인 통화인 경우, "구독 취소"할 필요는 없지만 사용자가 페이지를 떠날 경우 사용자가 부재 중일 때 응답을 적절하게 처리해야 합니다.
this.authorisationService
.authorize(data.username, data.password)
.subscribe((res: HttpResponse<object>) => {
this.handleLoginResponse(res);
},
(error: HttpErrorResponse) => {
this.messageService.error('Authentication failed');
},
() => {
this.messageService.info('Login has completed');
})
성가신 것부터 위험한 것까지
네트워크 속도가 평소보다 느리고 통화 시간이 5초 이상 소요되며 사용자가 로그인 보기를 벗어나 "지원 보기"로 이동한다고 상상해 보십시오.
구성 요소가 활성화되지 않았지만 구독일 수 있습니다.응답의 경우, 사용자의 핸들 응답() 구현에 따라 사용자의 경로가 갑자기 변경됩니다.
이건 좋지 않아요.
또한 사용자가 아직 로그인하지 않았다고 믿고 PC를 떠난다고 상상해 보십시오.하지만 논리적으로 사용자를 로그인하면 보안 문제가 발생합니다.
구독을 취소하지 않고 무엇을 할 수 있습니까?
보기의 현재 상태에 따라 전화를 걸 수 있습니다.
public isActive = false;
public ngOnInit(): void {
this.isActive = true;
}
public ngOnDestroy(): void {
this.isActive = false;
}
사용자.pipe(takeWhile(value => this.isActive))
보기가 활성 상태일 때만 응답이 처리되도록 합니다.
this.authorisationService
.authorize(data.username, data.password).pipe(takeWhile(value => this.isActive))
.subscribe((res: HttpResponse<object>) => {
this.handleLoginResponse(res);
},
(error: HttpErrorResponse) => {
this.messageService.error('Authentication failed');
},
() => {
this.messageService.info('Login has completed');
})
하지만 구독이 메모리 유출을 야기하지 않는다고 어떻게 확신할 수 있습니까?
해체 논리가 적용된 경우 기록할 수 있습니다.
구독의 해체 로직은 구독이 비어 있거나 구독이 취소된 경우 호출됩니다.
this.authorisationService
.authorize(data.username, data.password).pipe(takeWhile(value => this.isActive))
.subscribe((res: HttpResponse<object>) => {
this.handleLoginResponse(res);
},
(error: HttpErrorResponse) => {
this.messageService.error('Authentication failed');
},
() => {
this.messageService.info('Login has completed');
}).add(() => {
// this is the teardown function
// will be called in the end
this.messageService.info('Teardown');
});
구독을 취소할 필요는 없습니다.논리에 문제가 있으면 구독에 문제가 발생할 수 있음을 알아야 합니다.그리고 그들을 돌보세요.대부분의 경우 문제가 되지 않지만, 특히 자동화와 같은 중요한 작업에서는 "구독 취소" 또는 파이프 또는 조건부 콜백 함수와 같은 다른 논리적인 경우에 예상치 못한 동작을 주의해야 합니다.
왜 항상 구독을 취소하지 않습니까?
당신이 게시 또는 게시 요청을 한다고 상상해 보세요.서버는 어느 쪽이든 메시지를 수신합니다. 응답하는 데 시간이 걸립니다.구독을 취소하면 게시물이나 게시물을 취소할 수 없습니다.그러나 구독을 취소하면 대화 상자나 건배/메시지 등을 통해 응답을 처리하거나 사용자에게 알릴 수 없습니다.
사용자가 Put/Post 요청이 수행되지 않았다고 믿게 합니다.
상황에 따라 다릅니다.이러한 문제를 어떻게 처리할 것인지는 당신의 설계 결정입니다.
또한 새 HttpClient 모듈에서도 동일한 동작을 유지합니다.
당신은 이 기사를 꼭 읽어야 합니다.그것은 당신이 왜 http에서도 항상 구독을 취소해야 하는지 보여줍니다.
요청을 생성한 후 백엔드로부터 응답을 받기 전에 구성 요소가 필요하지 않다고 판단하여 삭제하는 경우, 헤드라인 등록은 구성 요소에 대한 참조를 유지하여 메모리 누수를 유발할 수 있습니다.
갱신하다
위의 확언은 사실인 것 같지만, 어쨌든 답이 돌아오면 http 구독은 어차피 파기됩니다.
자동으로 완료되는 관찰 항목(예: Http, 통화)에서 구독을 취소하면 안 됩니다.하지만 다음과 같은 무한 관측 가능 항목의 구독을 취소할 필요가 있습니다.Observable.timer()
.
이것을 이해하는 데 도움이 될 수 있는 좋은 부분은 구독 기능에 대한 호출이 없는 한 HTTP 요청이 이루어지지 않는다는 것입니다.이 페이지의 답변은 두 가지 방법을 제안하는 것처럼 보이지만, 각 문서에 표시된 대로 비동기 파이프에 의해 필요한 동작이 제어되기 때문에 큰 차이가 없습니다(단, '삭제 요청 만들기' 섹션의 뒷부분에 설명되어 있음).
비동기 파이프는 사용자를 위해 자동으로 구독(및 구독 취소)합니다.
사실, 그러한 관찰 가능한 것들이 구독 취소 기능을 호출함으로써 명시적으로 구독을 취소하는 어떤 예도 문서에서 찾기가 더 어렵습니다.
관찰 가능한 RxJS는 기본적으로 연관되어 있으며 구독에 따라 작동합니다.우리가 관찰 가능한 것을 만들고 그것을 완료하는 움직임을 만들면, 관찰 가능한 것은 자동으로 닫히고 구독을 취소합니다.
그들은 관찰자들과 같은 방식으로 일하지만 꽤 다른 순서로 일합니다.구성 요소가 파괴될 때 구독을 취소하는 것이 좋습니다.우리는 이것을 통해 나중에 그것을 할 수 있습니다.$manageSubscription.unsubscibe()
만약 우리가 아래에 언급된 것처럼 관찰 가능한 것을 만들었다면 다음과 같습니다.
새 관찰 가능 항목 반환((관찰자) => { ** // 콜드 상태 ** 관찰자.complete(*)) **
언급URL : https://stackoverflow.com/questions/35042929/is-it-necessary-to-unsubscribe-from-observables-created-by-http-methods
'programing' 카테고리의 다른 글
SQL Azure에서 쿼리 실행이 훨씬 느린 이유는 무엇입니까? (0) | 2023.05.12 |
---|---|
볼륨을 사용하여 도킹된 postgres 데이터베이스에서 데이터를 유지하는 방법 (0) | 2023.05.07 |
Blob에 저장된 미디어 파일의 내용 유형 설정 (0) | 2023.05.07 |
응답 이유.리디렉션으로 인해 시스템이 발생합니다.스레드화.스레드 중단 예외? (0) | 2023.05.07 |
Python Pandas read_exceltype str은 읽을 때 또는 to_csv를 통해 쓸 때 nan을 공백(')으로 대체합니다. (0) | 2023.05.07 |