BehaviorSubject的订阅者多次收到相同的next()元素

7
我正在使用BehaviorSubject实现shareDataService。我的问题是,每次调用服务的next()方法时,任何其他组件中的监听器订阅都会被多次调用,看起来像是接收到了多个相同的消息。这是预期行为吗?如何防止这种情况发生?
该服务是单例。 我不会多次调用changeMessage方法。
@Injectable()
export class ShareDataService {

    messageSource = new BehaviorSubject(someData);
    currentMessage: Observable = this.messageSource.asObservable();
    changeMessage(message) {
        this.messageSource.next(message);
    }

}

组件中的订阅

ngDoCheck() {
    this.shareDataService.currentMessage
        .pipe(takeUntil(this.ngUnsubscribe))
        .subscribe((message) => {
            //Do stuff
        }
    });
}

你能记录下所有订阅的成功回调的顺序并把它们展示给我们吗?BehaviorSubject 应该会发出最近一次发出的数据(包括之前和当前发出的数据)。但是为了确保,请您展示日志,其中包含所有成功回调的发生情况。 - Vinod Bhavnani
1
next(...) 将值发送给所有观察者(订阅者)。您可能会在同一个组件中创建多个订阅。 - martin
你能发一下你实际订阅的代码吗? - David R
@DavidR - 刚刚添加了 - Mac_W
@martin - 你是什么意思?我只在多个组件中订阅一次。 - Mac_W
3个回答

14
每次调用ngDoCheck()都会添加一个新的订阅。尝试使用first()仅获取一次值,然后自动取消订阅。
ngDoCheck() {
    this.shareDataService.currentMessage
        .pipe(first())
        .subscribe((message) => {
            // Do stuff
        }
    });
}
下次触发ngDoCheck时,它将添加另一个一次性订阅。
如果您的订阅目的仅是在变更检测期间获取当前值,则还可以向ShareDataService添加一个简单的get()函数,以返回其当前值。
get() {
    return this.messageSource.getValue();
}

1
我现在知道问题所在了!它现在正在发送多条消息,只是在变更检测时触发! - Mac_W
@Willys 我认为是因为两者都有活动订阅,所以当其中一个触发next()时,两个订阅都会触发,并导致两个reload()再次触发。 - Jeffrey Roosendaal
@JeffreyRoosendaal 感谢您的回复。关于这个问题的解决方案怎么样了?我为每个方法创建了主题并获取了事件,但我不确定这是否是一个好主意?您能否在这个问题上发表您的建议? - Jack

3

请尝试在ngOnDestroy()生命周期钩子中调用unsubscribe

ngOnDestroy() {
    this.shareDataService.currentMessage.unsubscribe();
}

希望这可以帮到您!

-1

我也遇到了类似的问题,后来发现我没有销毁我的next()

请检查下面的代码,并将其添加到您的onDestroy中。希望它能帮助到您!

ngOnDestroy() { this.messageSource.next(); }

祝一切顺利!!!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接