Rxjs 路由器重定向后调用订阅次数过多

Rxjs 路由器重定向后调用订阅次数过多,rxjs,angular6,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( takeW

我有一个简单的组件,它从状态中选择一些内容并列出更改:

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! ['a', 'b', 'c', 'd']
items changed! ['a', 'b', 'c', 'd']
items changed! ['a', 'b', 'c', 'd']

这里怎么了?我尝试了takeUntil和一个主题,我尝试了手动取消订阅-没有任何解决问题。

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

您可以更改项目!消息3次,因为在items$中有3个后续事件,所以订阅服务器被调用了3次

如果要忽略对象与前一个事件相同的更改事件,我建议使用distinctUntilChanged操作符

我将像这样:

项目$ .pipedistinctUntilChangedprevious,current=>previous[0]===current[0]&&/* .subscribeitems=>console.log'items changed!',项目; distinctUntilChanged具有可选回调,但在您的情况下,您将需要它,因为默认回调是previous,current=>previous==current,但对于字符串数组['a'、'b'、'c'、'd']!==['a','b','c','d']所以您必须编写比较函数。
将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();
}

我认为您的问题在于,当某个组件被销毁时,您并没有取消订阅

您正在使用takeWhile,但此操作符仅在其源发出时才作出反应。这意味着设置This.alive=false;什么也不做。只有在此之后发出此.items$,它才能完成链。它将被takeWhile捕获,这将完成整个链条。但这可能不会发生

建议使用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();
}