防止Angular 2中的内存泄漏?

时间:2015-12-25 09:56:19

标签: javascript angularjs memory-leaks angular rxjs

在Angular 2中有关于内存管理的任何特定缺陷,我应该知道吗?

管理组件状态以避免可能的泄漏的最佳做法是什么?

具体来说,我在ngOnDestroy方法中看到了一些人unsubscribing from HTTP observables。我应该一直这样做吗?

在Angular 1.X中,我知道当$scope被销毁时,其上的所有侦听器也会被自动销毁。 Angular 2组件中的可观察量如何?

@Component({
  selector: 'library',
  template: `
    <tr *ngFor="#book of books | async">
        <td>{{ book.title.text }}</td>
        <td>{{ book.author.text }}</td>
    </tr>
  `
})
export class Library {
    books: Observable<any>;

    constructor(private backend: Backend) {
        this.books = this.backend.get('/texts'); // <-- does it get destroyed
                                                 //     with the component?
    }
};

2 个答案:

答案 0 :(得分:16)

根据@katspaugh的要求

在您的特定情况下,无需手动取消订阅,因为这是Async管道的工作。

检查source code是否有AsyncPipe。为简洁起见,我发布了相关代码

class AsyncPipe implements PipeTransform, OnDestroy {
    // ...
    ngOnDestroy(): void {
        if (isPresent(this._subscription)) {
          this._dispose();
        }
    }

正如您所看到的,Async管道实现了OnDestroy,当它被销毁时,它会检查是否存在某些订阅并将其删除。

在这种特殊情况下你会重新发明轮子(抱歉重复自己)。这并不意味着您不能/不应该在您引用的任何其他情况下取消订阅。在这种情况下,用户在组件之间传递Observable以进行通信,因此最好手动取消订阅。

我不知道框架是否可以检测到任何 alive 订阅,并在组件被销毁时自动取消订阅,这当然需要更多调查。

我希望这能澄清一下Async管道。

答案 1 :(得分:4)

您不必取消订阅标准订阅,例如http.get()之后。 但您必须取消订阅自定义主题的订阅。如果您有一些组件,并且在其中您订阅了服务中的某些主题,那么每次显示该组件时,新订阅都将添加到主题中。

Problems with my service

请检查一下:Good solution to make your components 'clean'

我的个人方法 - 我的所有组件都从这个漂亮的课程中扩展出来:

&#13;
&#13;
import { OnDestroy, OnInit } from '@angular/core';
import { Subject } from 'rxjs/Subject';

/**
 * A component that cleans all subscriptions with oneself
 * https://stackoverflow.com/questions/38008334/angular-rxjs-when-should-i-unsubscribe-from-subscription
 * @class NeatComponent
 */
export abstract class NeatComponent implements OnDestroy, OnInit {
// Add '.takeUntil(this.ngUnsubscribe)' before every '.subscrybe(...)'
// and this subscriptions will be cleaned up on component destroy.

  protected ngUnsubscribe: Subject<any> = new Subject();

  public ngOnDestroy() {
    this.ngUnsubscribe.next();
    this.ngUnsubscribe.complete();
  }

  public ngOnInit(){}
}
&#13;
&#13;
&#13;

我只是在每次订阅之前添加 super()调用构造函数和 .takeUntil(this.ngUnsubscribe)

&#13;
&#13;
import { NeatComponent } from '../../types/neat.component';

@Component({
  selector: 'category-selector',
  templateUrl: './category-selector.component.pug'
})
export class CategorySelectorComponent extends NeatComponent {

  public constructor(
    private _shopService: ShopsService
  ) { super(); }

  public ngOnInit() {
    this._shopService.categories.takeUntil(this.ngUnsubscribe)
      .subscribe((categories: any) => {
        // your code here
      })
  }
}
&#13;
&#13;
&#13;