路由器重定向后订阅被调用太多次

时间:2019-02-07 15:53:46

标签: rxjs angular6

我有一个简单的组件,可以从状态中选择一些内容并侦听更改:

private items$: Observable<Item[]>;
private alive: boolean = true;

contructor(private store: Store<state>) {
  this.items$ = this.store.select(selectItems);
}

ngOnInit() {
  this.items$
    .pipe(
      takeWhile(() => this.alive)
    )
    .subscribe((items: Item[]) => {
      console.log('items changed!', items);
      // dispatch some actions
    });
}

ngOnDestroy() {
  this.alive = false;
}

它完美运行-每次更改项目时,我都会看到“项目已更改!”记录的字符串。当我重定向到其他地方并且组件被销毁时,订阅将无法运行。

但是当我重定向回该组件并再次激活订阅时,即使没有任何更改,它也会立即执行与开始时相同的更改。

例如,当我进入页面时:

items changed! null
items changed! ['a', 'b', 'c']
items changed! ['a', 'b', 'c', 'd']

当我重定向并返回到组件时:

items changed! ['a', 'b', 'c', 'd']
items changed! ['a', 'b', 'c', 'd']
items changed! ['a', 'b', 'c', 'd']

这是怎么了?我尝试过takeUntil和一个主题,但是我尝试过手动退订-没有任何方法可以解决问题。

3 个答案:

答案 0 :(得分:1)

对主题使用takeUntil

private items$: Observable<Item[]>;
private finalised = new Subject<void>();

contructor(private store: Store<state>) {
  this.items$ = this.store.select(selectItems);
}

ngOnInit() {
  this.items$
    .pipe(
      takeUntil(this.finalised)
    )
    .subscribe((items: Item[]) => {
      console.log('items changed!', items);
      // dispatch some actions
    });
}

ngOnDestroy() {
  this.finalised.next();
  this.finalised.complete();
}

答案 1 :(得分:0)

取消订阅或takeUntil将在组件销毁后完成,并且项在销毁前已更改。

您收到3次items changed!消息,因为在items$中有3个下一个事件,因此订阅者被呼叫3次。

如果您要忽略对象与先前事件相同的更改事件,建议使用distinctUntilChanged运算符。

我将看起来像这样:

items$
  .pipe(distinctUntilChanged((previous, current) => previous[0] === current[0] && ...)) /*
  .subscribe(items => console.log('items changed!', items));
  • distinctUntilChanged具有可选的回调,但是您将需要它,因为默认值是(previous, current) => previous === current,但是如果是字符串['a', 'b', 'c', 'd'] !== ['a', 'b', 'c', 'd'],则必须编写比较函数。

docs

答案 2 :(得分:0)

我认为您的问题实际上是在销毁组件时您没有取消订阅。

您正在使用takeWhile,但此操作符仅在其源发出时作出反应。这意味着设置this.alive = false;不会执行任何操作。只有在此之后发出this.items$时,它才能完成链。 takeWhile会将其捕获,从而完成整个链。但这可能不会发生。

推荐的方法是使用takeUntil或手动退订。这已经在这里讨论了很多次,这个答案应该告诉您确切要做什么:Angular/RxJs When should I unsubscribe from `Subscription`