【问题标题】:BehaviorSubject is executed more than onceBehaviorSubject 被多次执行
【发布时间】:2018-07-18 13:22:06
【问题描述】:

我在我的应用程序中使用 angular 4,我使用 behaviorSubject 在组件之间进行通信,一切正常

这是我的代码:

export class Globals {
loadStudentsByClass: BehaviorSubject<string> = new BehaviorSubject<string>(null);
}

export class ClassComponent implements OnInit {
selectNewClass() {
    console.log('About to select new class', this.selectedClass);
    this.globals.loadStudentsByClass.next(this.selectedClass); 
    this.globals.changeClassBehavior.next(true);
    this.router.navigateByUrl('');
  }
}

export class StudentComponent implements OnInit {
    this.globals.loadStudentsByClass.subscribe(value => {
          if (!isNullOrUndefined(value) && this.selectedClass !== value) {
            console.log('loadStudentsByClass=> home');
            this.loadStudentsByClass(this.selectedClass);
          }
        });
}

所以,我有组件ClassComponent 触发StudentComponent 调用函数loadStudentsByClass

这是我唯一称此行为主题的地方,但我发现我的行为主题不止一次发出

问题是为什么 behaviorSubject 执行loadStudentsByClass 不止一次,尽管this.globals.loadStudentsByClass.next(this.selectedClass); 只被调用一次

顺便说一句,执行次数取决于我在应用程序中访问的视图数

【问题讨论】:

  • 你能否在 stackblitz.com 上提供更多代码或更好的演示代码>

标签: angular behaviorsubject


【解决方案1】:

当组件被销毁时,您可能忘记取消订阅 StudentComponent。将订阅保存在类变量和ngOnDestroy()生命周期钩子调用subscription.unsubscribe()

【讨论】:

  • 我做到了,但仍然有同样的问题
【解决方案2】:

这将调用两次,因为每当 behaviorSubject 发生变化时,它都会发出最新的值。以前它是你给它的 null (作为默认值),接下来当服务响应到来时你正在做下一步,所以它会在更改后发出最新的值,这很公平。对于您的代码,您应该只检查

if(value){// do the stuff here}

【讨论】:

  • 我知道调用了两次(第一次为null,第二次有值),第二次有值后出现问题,相同的值,可以多调用超过两倍
  • 可能存在一些用例,您将离开该页面并再次访问,因此它可能会被调用,因为即使您离开该页面,您进行的订阅仍然有效。为避免这种情况,您应该执行以下操作: this.mySubscription = this.globals.loadStudentsByClass.subscribe(value => { if (!isNullOrUndefined(value) && this.selectedClass !== value) { console.log('loadStudentsByClass= > home'); this.loadStudentsByClass(this.selectedClass); } }); ngOnDestroy(){this.mySubscription.unsubscribe();}
  • 我注意到你提到了执行次数取决于我在应用程序中访问的视图数。当然,您必须取消订阅以避免多次订阅。这就是现在正在发生的事情。这也可能在将来导致内存泄漏。最好在角度的 ngOnDestroy() 生命周期钩子上取消订阅
  • 我这样做了,我保存了我的订阅然后销毁它,但仍然有同样的问题ngOnDestroy(): void { this.subscription.unsubscribe(); }。我应该销毁所有组件还是只销毁 StudentComponent 的订阅
  • 一旦组件不在内存中,您应该销毁所有订阅,无论您在哪里订阅;这是 ngOnDestroy()
【解决方案3】:

尝试一个没有初始值但仍会缓存您的流的重播主题:

export class Globals {
loadStudentsByClass = new ReplaySubject<string>(1);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-04-11
    • 2015-04-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多