如何退订ngrx/store?

How to unsubscribe from ngrx/store?

我有一个组件可以从订阅商店获取数据。

this.store.select('somedata').subscribe((state: any) => {
  this.somedata = state.data;
});

我想在组件不再存在时取消订阅,在我订阅某些可观察对象的其他地方,像这样:

this.service.data.subscribe(
   (result: any) => {//data}
);

我在 ngOnOnDestroy 上退订了它,如下所示:

ngOnDestroy(){
   this.service.data.unsubscribe();
}

但是如果商店我不能,它给我错误:

Property 'unsubscribe' does not exist on type 'Store<State>'

当你订阅时,你会收到一个订阅对象,你可以调用 unsubscribe()

const subscription = this.store.select('somedata').subscribe((state: any) => {
  this.somedata = state.data;
});
// later
subscription.unsubscribe();

ngOnInit(){
 this.someDataSubscription = this.store.select('somedata').subscribe((state: any) => {
  this.somedata = state.data;
 });
}

ngOnDestroy(){
  this.someDataSubscription.unsubscribe();
}

您不需要首先在您的模板中使用 | async 进行订阅。 您从商店获得的一切都是可见的,让 angular 处理您的订阅。 这里是api

不直接调用subscribe方法也可以取值,像async pipe一样取值

@Component({
    template: `
        <div>Current Count: {{ counter | async }}</div>
    `
})
class MyAppComponent {
    counter: Observable<number>;

    constructor(private store: Store<AppState>){
        this.counter = store.select('counter');
    }
}

这里我们使用异步管道来获取值。 异步管道订阅 Observable 或 Promise 和 returns 它发出的最新值。当发出新值时,异步管道标记要检查更改的组件。当组件被销毁时,异步管道会自动取消订阅以避免潜在的内存泄漏。

有一种比得票最高的答案更好的方法,您无需管理一堆订阅,只需管理一个。然后,您可以拥有任意数量的订阅,而无需创建一堆不必要的变量。

  public ngDestroyed$ = new Subject();

  public ngOnDestroy() {
    this.ngDestroyed$.next();
  }

  public ngOnInit() {
    this.myWhateverObs$
        .pipe(takeUntil(this.ngDestroyed$))
        .subscribe((val)=> { this.whatever()});
    this.myWhateverNPlusOne$
        .pipe(takeUntil(this.ngDestroyed$))
        .subscribe((val)=> { this.whatever()})
  }

我用过的最简洁的方法是使用 ngx-take-until-destroy 库。 您的代码将是这样的:

this.store.select('somedata')
    .pipe(untilDestroyed(this))
    .subscribe((state: any) => {
        this.somedata = state.data;
    });

您还需要在 class 中使用 ngOnDestroy() 方法。

此答案基于 and 提供的答案。

无外部库解决方案

避免每个组件与主题及其代码膨胀的一种方法是使用基本组件(使用 Angular 10.0.6 测试):

base.component.ts

import { Subject } from "rxjs";
import { Component } from "@angular/core";

@Component({
    selector: "app-base-component",
    template: ""
})
export class BaseComponent {
    public ngDestroyed$ = new Subject();

    public onDestroy(): void {
        this.ngDestroyed$.next();
    }
}

foo.component.ts

@Component({
    selector: "app-foo",
    templateUrl: "./foo.component.html",
    styleUrls: ["./foo.component.scss"]
})
export class FooComponent extends BaseComponent implements OnInit, OnDestroy {

    fooList$: Observable<FooModel[]>;

    @ViewChild(DataBindingDirective) dataBinding: DataBindingDirective;
    public gridData: any[];
    public gridView: any[];

    public mySelection: string[] = [];

    constructor(private readonly store: Store<AppState>) {
        super();
    }
    ngOnDestroy(): void {
        this.onDestroy();
    }

    ngOnInit(): void {
        this.store.dispatch(ApplicationFooItemsRequestedAction());
        this.fooList$ = this.store.select(selectAllApplicationFooItems);

        this.fooList$.pipe(takeUntil(this.ngDestroyed$)).subscribe(ul => {
            // do stuff with items
        });
    }
}

使用外部库

您可以使用 @ngneat/until-destroy 库来避免自定义代码并支持其他场景(例如在服务中)

@Component({
    selector: "app-foo",
    templateUrl: "./foo.component.html",
    styleUrls: ["./foo.component.scss"]
})
export class FooComponent extends BaseComponent implements OnInit, OnDestroy {

    ngOnInit(): void {
        this.store.dispatch(ApplicationFooItemsRequestedAction());
        this.fooList$ = this.store.select(selectAllApplicationFooItems);

        this.fooList$.pipe(takeUntil(untilDestroyed(this))).subscribe(ul => {
             // do stuff with items
        });
     }

}