我是否需要在 ngOnDestroy 中使用 `complete()` takeUntil Subject?

戈加·科雷利

为了避免组件内部的 Observable 内存泄漏,我takeUntil()在订阅 Observable 之前使用了运算符。

我在我的组件中写了这样的东西:

private unsubscribe$ = new Subject();

ngOnInit(): void {
  this.http
    .get('test')
    .pipe(takeUntil(this.unsubscribe$))
    .subscribe((x) => console.log(x));
}

ngOnDestroy(): void {
  this.unsubscribe$.next();
  this.unsubscribe$.complete(); // <--- ??
}

最后我的问题如下:

我需要写this.unsubscribe$.complete();还是next()就够了?

unsubscribe$要由垃圾收集器没有完成被抓住?

请解释是否存在差异或无关紧要。我不希望我的组件出现内存泄漏。

布莱恩60

简短的回答,不,这不是必需的,但也无妨。

长答案:

只有在阻止垃圾收集时才需要取消订阅/完成 angular ,因为订阅涉及某些主题,该主题将因收集而比组件寿命更长。这就是内存泄漏的产生方式。

如果我有服务:

export class MyService {
  mySubject = new Subject();
}

它在 root 中提供,并且只在 root 中提供(这意味着它是一个单例并且在实例化后永远不会被销毁)以及一个注入此服务并订阅它的主题的组件

export class MyLeakyComponent {
  constructor(private myService: MyService) {
    this.myService.mySubject.subscribe(v => console.log(v));
  }
}

这是造成内存泄漏。为什么?因为 MyLeakyComponent 中的订阅是由 MyService 中的主题引用的,所以只要 MyService 存在并持有对它的引用,MyLeakyComponent 就不能被垃圾收集,并且 MyService 将在应用程序的生命周期内存在。每次实例化 MyLeakyComponent 时,这都会复合。要解决此问题,您必须取消订阅或在组件中添加终止运算符。

但是这个组件:

export class MySafeComponent {
  private mySubect = new Subject();
  constructor() {
    this.mySubject.subscribe(v => console.log(v));
  }
}

是完全安全的,可以毫无问题地进行垃圾收集。没有外部持久化实体持有对它的引用。这也是安全的:

@Component({
  providers: [MyService]
})
export class MyNotLeakyComponent {
  constructor(private myService: MyService) {
    this.myService.mySubject.subscribe(v => console.log(v));
  }
}

现在注入的服务由组件提供,因此服务和组件将一起销毁,并且可以安全地进行垃圾回收,因为外部引用也将被销毁。

这也是安全的:

export class MyHttpService { // root provided
  constructor(private http: HttpClient) {}

  makeHttpCall() {
    return this.http.get('google.com');
  }
}

export class MyHttpComponent {
  constructor(private myhttpService: MyHttpService) {
    this.myhttpService.makeHttpCall().subscribe(v => console.log(v));
  }
}

因为http调用是一类自终止的observable,所以在调用完成后自然终止,所以不需要手动完成或取消订阅,因为外部引用一旦自然完成就消失了。

至于你的例子:unsubscribe$主题是组件本地的,因此它不可能导致内存泄漏。任何地方学科都是如此。

关于最佳实践的说明:Observables 是 COMPLEX。一个看起来完全安全的人,可能以一种微妙的方式涉及一个外部主题。为了完全安全/如果您对 observables 不是很满意,通常建议您取消订阅所有非终止 observables。除了你自己花时间做这件事外,没有其他缺点。我个人认为 unsubscribe$ 信号方法很糟糕,并认为它会污染/混淆您的流。对我来说最简单的是这样的:

export class MyCleanedComponent implements OnDestroy {
  private subs: Subscription[] = [];
  constructor(private myService: MyService) {
    this.subs.push(
      this.myService.mySubject.subscribe(v => console.log(v)),
      this.myService.mySubject1.subscribe(v => console.log(v)),
      this.myService.mySubject2.subscribe(v => console.log(v))
    );
  }

  ngOnDestroy() {
    this.subs.forEach(s => s.unsubscribe());
  }
}

但是,防止泄漏的唯一最佳方法是尽可能使用 angular 提供的异步管道。它为您处理所有订阅管理。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

使用takeUntil模式退订Observable时是否需要完成Subject?

来自分类Dev

RxJS:takeUntil()角组件的ngOnDestroy()

来自分类Dev

使用takeUntil进行可观察的Angular销毁:ngOnDestroy中缺少.next()时会发生什么

来自分类Dev

RxJS:takeUntil忽略Subject事件

来自分类Dev

我是否需要在 recyclerView 或 recyclerView 中使用列表视图?

来自分类Dev

我是否需要在synced(anyObject)块中使用AtomicInteger?

来自分类Dev

在不调用 complete 的情况下使用 reduce Subject

来自分类Dev

在父组件中使用单个ngOnDestroy

来自分类Dev

使用takeUntil()关闭订阅

来自分类Dev

Angular RxJS:如果我使用异步管道,我需要做 .takeUntil(this.destroy$) 吗?

来自分类Dev

takeUntil()是否可以与Observable <void>一起使用?

来自分类Dev

是否需要在Flink中使用Windows?

来自分类Dev

我是否仍需要在使用子级父代NSManagedObjectContext的应用程序中使用mergeChangesFromContextDidSaveNotification

来自分类Java

我是否需要在实现时再次使用@Nonnull?

来自分类Dev

我是否需要在<button>上使用role =“ button”?

来自分类Dev

我是否需要在指针向量上使用互斥锁?

来自分类Dev

带有Zeus的RSpec 3.1,我是否需要在spec_helper中使用“ rspec / rails”?

来自分类Dev

我是否需要在POST中使用与GET相同的VM来重新加载索引?

来自分类Dev

我是否需要在单语言UWP应用程序中使用create_async?

来自分类Dev

我们是否需要在BCrypt中使用固定盐?

来自分类Dev

我是否需要C#创建要在IronPython中使用的dll?

来自分类Dev

AngualrJs:我是否需要在控制器中使用$ scope?

来自分类Dev

我是否需要在导航控制器子视图中使用GADRequest()的单例?

来自分类Dev

我是否需要在FBO中使用RenderBufferObject来渲染具有保留Alpha通道的纹理?

来自分类Dev

我是否需要在实体框架6中使用POCO类

来自分类Dev

我是否需要在函数内的data.table对象中使用copy()?

来自分类Dev

我是否需要在case表达式中使用else子句?

来自分类Dev

我是否需要在 HTML 表单中使用 htmlspecialchars() 用户输入来防止 XSS?

来自分类Dev

我是否需要在基于 cookie 的 API 中使用 CSRF 令牌?

Related 相关文章

  1. 1

    使用takeUntil模式退订Observable时是否需要完成Subject?

  2. 2

    RxJS:takeUntil()角组件的ngOnDestroy()

  3. 3

    使用takeUntil进行可观察的Angular销毁:ngOnDestroy中缺少.next()时会发生什么

  4. 4

    RxJS:takeUntil忽略Subject事件

  5. 5

    我是否需要在 recyclerView 或 recyclerView 中使用列表视图?

  6. 6

    我是否需要在synced(anyObject)块中使用AtomicInteger?

  7. 7

    在不调用 complete 的情况下使用 reduce Subject

  8. 8

    在父组件中使用单个ngOnDestroy

  9. 9

    使用takeUntil()关闭订阅

  10. 10

    Angular RxJS:如果我使用异步管道,我需要做 .takeUntil(this.destroy$) 吗?

  11. 11

    takeUntil()是否可以与Observable <void>一起使用?

  12. 12

    是否需要在Flink中使用Windows?

  13. 13

    我是否仍需要在使用子级父代NSManagedObjectContext的应用程序中使用mergeChangesFromContextDidSaveNotification

  14. 14

    我是否需要在实现时再次使用@Nonnull?

  15. 15

    我是否需要在<button>上使用role =“ button”?

  16. 16

    我是否需要在指针向量上使用互斥锁?

  17. 17

    带有Zeus的RSpec 3.1,我是否需要在spec_helper中使用“ rspec / rails”?

  18. 18

    我是否需要在POST中使用与GET相同的VM来重新加载索引?

  19. 19

    我是否需要在单语言UWP应用程序中使用create_async?

  20. 20

    我们是否需要在BCrypt中使用固定盐?

  21. 21

    我是否需要C#创建要在IronPython中使用的dll?

  22. 22

    AngualrJs:我是否需要在控制器中使用$ scope?

  23. 23

    我是否需要在导航控制器子视图中使用GADRequest()的单例?

  24. 24

    我是否需要在FBO中使用RenderBufferObject来渲染具有保留Alpha通道的纹理?

  25. 25

    我是否需要在实体框架6中使用POCO类

  26. 26

    我是否需要在函数内的data.table对象中使用copy()?

  27. 27

    我是否需要在case表达式中使用else子句?

  28. 28

    我是否需要在 HTML 表单中使用 htmlspecialchars() 用户输入来防止 XSS?

  29. 29

    我是否需要在基于 cookie 的 API 中使用 CSRF 令牌?

热门标签

归档