【问题标题】:a mechanism for auto unsubscribing from observables一种自动取消订阅 observables 的机制
【发布时间】:2019-10-14 20:33:25
【问题描述】:

为了在确保我取消订阅可观察订阅时尝试并干燥我的代码,我创建了这个类:

// autounsubscribe.ts 

import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';

export abstract class AutoUnsubscribe {
    protected unsubscriber$ = new Subject<void>();

    ngOnDestroy(): void {
        this.unsubscriber$.next();
        this.unsubscriber$.complete();
        console.log('unsubscribed');
    }

    protected subscribe(observable, fn) {
        return observable.pipe(takeUntil(this.unsubscriber$)).subscribe(fn);
    }
}

这现在可以由其他类扩展,如下所示:

import { Component } from '@angular/core';
import { Observable } from 'rxjs';
import { AutoUnsubscribe } from './autounsubscribe';

@Component({
    selector: 'nio-init',
    templateUrl: './init.component.html',
    styleUrls: ['./init.component.scss']
})
export class InitComponent extends AutoUnsubscribe {
    private obs$: Observable<boolean> = new Observable();

    constructor() {
        super();

        this.subscribe(this.obs$, data => {
            console.log('new event', data);
        });
    }
}

这可行:当可观察对象发生变化时,订阅会接收数据,当这个组件被销毁时,控制台会记录“取消订阅”

但是,由于我是一个相对的菜鸟打字稿编码员,我想知道是否

A)这是最合适的方式,因为我开始不喜欢“扩展/继承”,因为它往往会隐藏一些东西。比如“this.subscribe 是从哪里来的?检查......哦,是的,必须在我要扩展的类中”等

B) 我很想通过装饰器提供相同的功能,但不完全确定是否可行

C) 其他人如何管理这个过程。我见过几个选项,但大多数都涉及很多 DRY 问题

感谢您的想法、cmets 和建议 ;)

【问题讨论】:

  • 只使用异步管道
  • 当你有一个带有 ngOnDestroy 的 super 时,如果你的组件实现了 OnDestroy,你必须记得调用 super.ngOnDestroy(),保证你会忘记这样做!

标签: typescript inheritance rxjs


【解决方案1】:

您的想法很聪明,但我认为您最好尝试使用 async 管道将可观察对象绑定到您的模板。

export class InitComponent {
    user$: Observable<UserModel>;

    constructor(userService: UserService) {
        this.user$ = userService.fetchUserData();
    }
}

然后您可以轻松地在模板中使用您的 observable 属性,如下所示:

<div *ngIf="user$ | async as user">
  <h3>{{ user.name }}</h3>
  <p>{{ user.bio }}</p>
</div>

使用async pipe,您不必担心退订。

如果您想要更多自定义的派生属性,您仍然可以利用async 管道。

export class InitComponent {
    user$: Observable<UserModel>;

    get isUserQualified$(): Observable<boolean> {
        return this.user$.pipe(map(u => u.age > 21 && u.weight >= 100));
    }

    constructor(userService: UserService) {
        this.user$ = userService.fetchUserData();
    }
}
<div *ngIf="user$ | async as user">
  <h3>{{ user.name }}</h3>
  <p>{{ user.bio }}</p>
</div>
<div *ngIf="isUserQualified$ | async">
  <p>Special content for qualified users!</p>
</div>

您可以使用许多 rxjs 运算符来映射、过滤、排列或任何您需要对可观察状态执行的操作。

【讨论】:

    【解决方案2】:

    Warbell 创建了一个名为subsink 的库,用于优雅地取消订阅组件中的多个订阅。它不会自动订阅您的订阅,但您可以将多个可观察对象添加到数组中一起取消订阅

    可以看John Papa in a ng-conf 2019这个插件的小介绍

    【讨论】:

      猜你喜欢
      • 2017-03-26
      • 2020-10-28
      • 2022-11-30
      • 2017-08-24
      • 2017-12-17
      • 2013-04-16
      • 2019-01-18
      • 1970-01-01
      • 2019-05-06
      相关资源
      最近更新 更多