Is it necessary to unsubscribe from observables created by Http methods?

前端 未结 9 1666
醉酒成梦
醉酒成梦 2020-11-22 04:50

Do you need to unsubscribe from Angular 2 http calls to prevent memory leak?

 fetchFilm(index) {
        var sub = this._http.get(`http://example.com`)
              


        
9条回答
  •  感情败类
    2020-11-22 05:13

    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 executed. That execution is now considered out-of-context and can result in many things including very low performance.

    So, the 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('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
      }
    }
    

提交回复
热议问题