IT story

Http 메서드로 만든 Observable을 구독 취소해야합니까?

hot-time 2020. 5. 26. 07:49
반응형

Http 메서드로 만든 Observable을 구독 취소해야합니까?


메모리 누수를 방지하기 위해 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이는 click예를 들어 DOM 리스너 처럼 무한한 데이터 스트림이 방출 될 수 있습니다 .

감사합니다. @rubyboy


사람들은 무엇에 대해 이야기하고 있습니까 !!!

확인 가능하므로 구독을 취소해야하는 두 가지 이유가 있습니다. 중요한 두 번째 이유에 대해 아무도 많이 이야기하지 않는 것 같습니다!

1) 자원을 정리하십시오. 다른 사람들이 말했듯이 이것은 HTTP 옵저버 블에게는 무시할만한 문제입니다. 그냥 정리해

2) subscribe핸들러가 실행되지 않도록하십시오 .

(HTTP의 경우 실제로 브라우저에서 요청을 취소하므로 응답을 읽는 데 시간을 낭비하지 않지만 실제로는 아래 주요 요점을 제외하고는 아닙니다.)

숫자 2의 관련성은 구독 처리기의 기능에 따라 다릅니다.

귀하의 경우 subscribe()핸들러 함수가 호출 어떤이 닫혀있는 경우 바람직하지 않은 또는 배치되어 부작용의 종류를 가지고 당신은 탈퇴 (또는 조건부 논리를 추가) 실행되는 것을 방지하기 위해해야합니다.

몇 가지 경우를 고려하십시오.

1) 로그인 양식. 사용자 이름과 비밀번호를 입력하고 '로그인'을 클릭하십시오. 서버 속도가 느리고 Esc를 눌러 대화 상자를 닫으려면 어떻게해야합니까? 로그인하지 않았다고 가정 할 수도 있지만 탈출을 누른 후에 http 요청이 반환되면 거기에있는 모든 논리를 계속 실행합니다. 이로 인해 계정 페이지로 리디렉션되거나 원치 않는 로그인 쿠키 또는 토큰 변수가 설정 될 수 있습니다. 이것은 아마도 사용자가 기대하지 않은 것입니다.

2) '이메일 보내기'양식.

If the subscribe handler for 'sendEmail' does something like trigger a 'Your email is sent' animation, transfer you to a different page or tries to access anything that has been disposed you may get exceptions or unwanted behavior.

Also be careful not to assume unsubscribe() means 'cancel'. Once the HTTP message is in-flight unsubscribe() will NOT cancel the HTTP request if it's already reached your server. It will only cancel the response coming back to you. And the email will probably get sent.

If you create the subscription to send the email directly inside a UI component then you probably would want to unsubscribe on dispose, but if the email is being sent by a non-UI centralized service then you probably wouldn't need to.

3) An Angular component that is destroyed / closed. Any http observables still running at the time will complete and run their logic unless you unsubscribe in onDestroy(). Whether the consequences are trivial or not will depend upon what you do in the subscribe handler. If you try to update something that doesn't exist anymore you may get an error.

Sometimes you may have some actions you would want if the component is disposed, and some you wouldn't. For example maybe you have a 'swoosh' sound for a sent email. You'd probably want this to play even if the component was closed, but if you try to run an animation on the component it would fail. In that case some extra conditional logic inside subscribe would be the solution - and you would NOT want to unsubscribe the http observable.

So in answer to the actual question, no you don't need to do it to avoid memory leaks. But you need to do it (often) to avoid unwanted side effects being triggered by running code that may throw exceptions or corrupt your application state.

Tip: The Subscription contains a closed boolean property that may be useful in advanced cases. For HTTP this will be set when it completes. In Angular it might be useful in some situations to set a _isDestroyed property in ngDestroy which can be checked by your subscribe handler.

Tip 2: If handling multiple subscriptions you can create an ad-hoc new Subscription() object and add(...) any other subscriptions to it - so when you unsubscribe from the main one it will unsubscribe all the added subscriptions too.


Calling the unsubscribe method is rather to cancel an in-progress HTTP request since this method calls the abort one on the underlying XHR object and remove listeners on the load and error events:

// From the XHRConnection class
return () => {
  _xhr.removeEventListener('load', onLoad);
  _xhr.removeEventListener('error', onError);
  _xhr.abort();
};

That said, unsubscribe removes listeners... So it could be a good idea but I don't think that it's necessary for a single request ;-)

Hope it helps you, Thierry


Also with the new HttpClient module, remains the same behaviour 꾸러미 /common/http/src/jsonp.ts


You shouldn't unsubscribe from observables that completes automatically (e.g Http, calls). But it's necessary to unsubscribe from infinite observables like Observable.timer().


You should definitely read this article. It shows you why you should always unsubscribe even from http.

If after creating the request but before receiving an answer from the back-end you deem the component unnecessary and destroy it, your subscription will maintain the reference to the component thus creating a chance for causing memory leaks.

Update

The above affirmation seems to be true, but anyway, when the answer comes back the http subscription is destroyed anyway


Unsubscribing is a MUST if you want a deterministic behavior on all network speeds.

Imagine that component A is rendered in a tab - You click a button to send a 'GET' request out. It takes 200 ms for the response to come back. So, you are safe to close the tab at any moment knowing that, the machine will be faster than you & the http response is processed and is complete before the tab is closed and component A is destroyed.

How about on a very slow network? You click a button, the 'GET' request takes 10 seconds to receive its response, but 5 seconds into waiting you decide to close the tab. That will destroy component A to be garbage-collected at a later time. Wait a minute!, we did not unsubscribe -- now 5 seconds later, a response comes back and the logic in the destroyed component will be execute. That execution is now considered out-of-context and can result in many things including very low performance.

So, best practice is to use takeUntil() and unsubscribe from http calls when the component is destroyed.

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
  }
}

RxJS observable are basically associated and work accordingly you subscribe it. When we create the observable and the movement we complete it, observable automatically gets closed and unsubscribed.

그들은 같은 방식으로 감시자들과 작동하지만 순서는 다릅니다. 구성 요소가 파괴 될 때 구독을 취소하는 것이 더 좋습니다 . this. $ manageSubscription.unsubscibe ()

아래와 같은 문법을 관찰 할 수 있다면

** 새로운 Observable 반환 ((observer) => {** // 차가운 상태에서 관찰 가능 ** observer.complete () **}) **

참고 URL : https://stackoverflow.com/questions/35042929/is-it-necessary-to-unsubscribe-from-observables-created-by-http-methods

반응형