为什么角度订阅多次?

时间:2018-07-12 05:19:41

标签: angular rxjs

我有这样的结构:

  • product.service(用于服务)
  • 产品搜索组件(用于设置当前选中的对象)
  • 比较产品组件(用于订阅当前选中的对象)

每当加载比较产品时,我都想订阅服务中的对象。起初看起来还不错。但是,当我按下后退按钮进入产品搜索,然后再次加载比较产品时,它订阅了两次。当我返回并再次加载时,它被调用了三次。返回,再次加载,调用四次,依此类推。

这些是代码:

服务:

//product.service
.......
private checkedSrc = new BehaviorSubject([]);
currentChecked = this.checkedSrc.asObservable();

.......
setChecked(checked: string[]){
    this.checkedSrc.next(checked);
}

resetChecked(){
    this.checkedSrc.next([]);
}
.......

产品搜索组件:

......
compare(){
    this.products_valid = true;
    this.productSvc.setChecked(this.checked);
    this.router.navigate(['compare']);
}
......

比较产品组件:

...
products: string[];
isLoading: boolean = true;

constructor(
  private productSvc: ProductsService
) { }

ngOnInit() {
  this.productSvc.currentChecked.subscribe(p => {this.products = p; console.log(this.products)})
}

我尝试过它,而没有导航到比较组件。当我第一次调用比较函数时,它会订阅一次,再次调用比较时,它会订阅两次,再次调用时,它会订阅三次,依此类推。

......
compare(){
    this.products_valid = true;
    this.productSvc.setChecked(this.checked);
    this.productSvc.currentChecked.subscribe(p =>{console.log(p);})
}
......

调用它的按钮:

<div class="row">
  <div class="col-md-6">
    <button class="btn btn-primary" style="margin-top: 20px;" (click)="compare()">Compare</button>
  </div>
</div>

每次比较方法调用时,我也尝试过使用resetChecked()重置对象,但仍然相同...

3 个答案:

答案 0 :(得分:4)

该组件销毁后,您需要退订可观察对象。每次加载组件时,您都有1个订阅。

答案 1 :(得分:3)

每当您呼叫subscribe的源(在这种情况下为checkSrc时)都会被告知新订户想要获取数据。来源不知道您何时离开该页面,但仍会跟踪一个订户。返回时,subscribe再次被调用,现在源有两个订阅者。

您可以通过多种方法解决此问题。第一种是退订ngOnDestroy方法:

subscription;

ngOnInit() {
  this.subscription = this.productSvc.currentChecked.subscribe(p => {this.products = p; })
}

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

更好的选择是使用async管道。

ngOnInit() {
 this.products = this.productSvc.currentChecked();
}

在您的HTML中:

<ul>
  <li *ngFor="let product of products | async">{{product.name}}</li>
</ul>

如您所见,this.products不再是指产品,而是产品流。为了在模板中使用,请添加async管道。优点之一是您不需要订阅和退订。

答案 2 :(得分:0)

在Angular 6中,如果您使用的是ngOnDestroy方法,请记住使用对订阅的引用。

needles

如果在ngOnDestroy中直接在this.myService.myMethod上调用取消订阅,则最终将收到“ ObjectUnsubscribedError”异常。