如何使用 takeUntil RxJS 操作符声明式管理订阅

简介

Angel处理从可观察订阅的取消订阅,如从HTTp服务返回的订阅或在使用Async pipe.]时然而,对于其他情况,管理所有订阅并确保取消订阅长期订阅可能很快就会变得困难。取消订阅大多数订阅的政策也会有其自身的问题。

在本文中,您将看到一个依赖于手动订阅和取消订阅的示例角度应用程序。然后,您将把它与一个示例的角度应用程序进行比较,该应用程序使用takUntil操作符来声明性地管理订阅。

前提条件

如果您想继续阅读本文,您将需要:

  • 熟悉RxJS library,,特别是可观察订阅会更好。
  • 熟悉阿波罗和GraphQL将有所帮助,但不是必需的。

本教程已通过Node v15.3.0、npmv6.14.9、@angular/corev11.0.4、rxjsv6.6.3、apollo-angularv2.1.0、graph-tagv2.11.0验证。本文经过编辑,以反映从较早版本的@Angel/corerxjs迁移的变化。

手动退订

让我们从一个例子开始,你将手动取消订阅两个订阅。

在本例中,代码订阅了ApollowatchQuery以从GraphQL端点获取数据。

该代码还创建了一个间隔可观察值,当onStartInterval方法被调用时,您可以订阅它。

 1import { Component, OnInit, OnDestroy } from '@angular/core';
 2
 3import { Subscription, interval } from 'rxjs';
 4
 5import { Apollo } from 'apollo-angular';
 6import gql from 'graphql-tag';
 7
 8@Component({ ... })
 9export class AppComponent implements OnInit, OnDestroy {
10  myQuerySubscription: Subscription;
11  myIntervalSubscription: Subscription;
12
13  constructor(private apollo: Apollo) {}
14
15  ngOnInit() {
16    this.myQuerySubscription = this.apollo.watchQuery<any>({
17      query: gql`
18        query getAllPosts {
19          allPosts {
20            title
21            description
22            publishedAt
23          }
24        }
25      `
26    })
27    .valueChanges
28    .subscribe(({data}) => {
29      console.log(data);
30    });
31  }
32
33  onStartInterval() {
34    this.myIntervalSubscription = interval(250).subscribe(value => {
35      console.log('Current value:', value);
36    });
37  }
38
39  ngOnDestroy() {
40    this.myQuerySubscription.unsubscribe();
41
42    if (this.myIntervalSubscription) {
43      this.myIntervalSubscription.unsubscribe();
44    }
45  }
46}

现在想象一下,您的组件有许多类似的订阅,当组件被销毁时,它可能很快成为一个相当大的过程,以确保所有内容都被取消订阅。

使用takUntil声明退订

解决方案是使用takeUntil操作符组合订阅,并使用在ngOnDestroy 生命周期钩子中发出truthy值的主题。

下面的代码片段做了完全相同的事情,但这一次代码将以声明方式取消订阅。您会注意到一个额外的好处是您不再需要保留对我们订阅的引用。

 1import { Component, OnInit, OnDestroy } from '@angular/core';
 2
 3import { Subject, interval } from 'rxjs';
 4import { takeUntil } from 'rxjs/operators';
 5
 6import { Apollo } from 'apollo-angular';
 7import gql from 'graphql-tag';
 8
 9@Component({ ... })
10export class AppComponent implements OnInit, OnDestroy {
11  destroy$: Subject<boolean> = new Subject<boolean>();
12
13  constructor(private apollo: Apollo) {}
14
15  ngOnInit() {
16    this.apollo.watchQuery<any>({
17      query: gql`
18        query getAllPosts {
19          allPosts {
20            title
21            description
22            publishedAt
23          }
24        }
25      `
26    })
27    .valueChanges
28    .pipe(takeUntil(this.destroy$))
29    .subscribe(({data}) => {
30      console.log(data);
31    });
32  }
33
34  onStartInterval() {
35    interval(250)
36    .pipe(takeUntil(this.destroy$))
37    .subscribe(value => {
38      console.log('Current value:', value);
39    });
40  }
41
42  ngOnDestroy() {
43    this.destroy$.next(true);
44    this.destroy$.unsubscribe();
45  }
46}

请注意,使用像takUntil这样的操作符而不是手动取消订阅也会完成可观察对象,触发对可观察对象的任何完成事件。

请务必检查您的代码,以确保这不会产生任何意外的副作用。

结论

在本文中,您了解了如何使用takUntil进行声明性退订。取消订阅不必要的订阅有助于防止内存泄漏。声明式取消订阅允许您不需要对订阅的引用。

还有其他类似的RxJS操作符-如taketakeWhilefirst -它们都将完成观察对象。

如果您想了解更多有关ANGLE的信息,请查看我们的ANGLE主题页面以获取练习和编程项目。

Published At
Categories with 技术
Tagged with
comments powered by Disqus