自动取消订阅可观察对象的机制

时间:2019-05-22 20:16:02

标签: typescript inheritance rxjs

为了尝试使我的代码干燥,以确保我取消可观察的订阅,我创建了此类:

// 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);
        });
    }
}

这有效:订阅在可观察到的更改时接收数据,并且在销毁此组件时,控制台记录“未订阅”

但是,由于我是相对的noob打字员,所以我想知道

A)这是最合适的方法,因为我开始爱上“扩展/继承”,因为它倾向于隐藏事物。就像“ this.subscribe的来源是哪里?检查...哦,是的,必须在我要从中扩展的课程中”等

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

C)其他人如何管理此过程。我已经看到了几种选择,但是其中大多数都涉及很多DRY问题

我会很感激您的想法,意见和建议;)

2 个答案:

答案 0 :(得分:0)

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

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

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

然后,您可以像这样轻松地在模板中使用可观察属性:

<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运算符来映射,过滤,排列或进行任何可观察到的状态。

答案 1 :(得分:0)

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

您可以通过John Papa in a ng-conf 2019

看到有关此插件的简短介绍。