'Angular 2: BehaviorSubject, avoid with multiple subscription
Hi I have following problem in my Angular 2 app.
I have BroadcastService:
@Injectable()
export class BroadcastService {
private broadcastSubject: BehaviorSubject<Event> = new BehaviorSubject<Event>(0);
public next(event: Event): void {
return this.broadcastSubject.next(event);
}
public subject(event: Event): Observable<Event> {
return this.broadcastSubject.asObservable().filter(e => e === event);
}
}
Which I use in components like this:
export class MyComponent implements OnInit {
constructor(public broadcastService: BroadcastService) {
this.broadcastService.subject(Event.BLA_EVENT).subscribe(() => this.bla());
}
...
Whenever I route to '/mycomponent' the MyComponent.constructor is called, so the Event.BLA_EVENT is subscriped multiple times.
Any advice how to prevent multiple time subscription?
Solution 1:[1]
I had a similar problem and I solved it by checking the quantity of the observers on the event.
The option using ngOnDestroy may be the best, but another approach could be something like:
constructor(public broadcastService: BroadcastService) {
if(this.broadcastService.subject(Event.BLA_EVENT).observers.length == 0) {
this.broadcastService.subject(Event.BLA_EVENT).subscribe(() => this.bla());
}
}
Solution 2:[2]
Now you can use BroadcastChannel in almost all browsers (see caniuse):
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class BroadcastService {
private consumer: BroadcastChannel;
private producer: BroadcastChannel;
constructor() {
this.consumer = new BroadcastChannel('pluginGlobalEventBus');
this.producer = new BroadcastChannel('pluginGlobalEventBus');
}
postMessage(message: any): void {
this.producer.postMessage(message);
}
addEventListener(eventName, listener): void {
this.consumer.addEventListener('message', event => {
if (event.data.name === eventName) {
listener(event.data.value);
}
});
}
}
export class EmitEvent {
constructor(public name: any, public value?: any) {}
}
usage:
// sending
const event = new EmitEvent('logEvent', 'BUTTON_CLICKED');
this.broadcastService.postMessage(event);
// listening
this.broadcastService.addEventListener('logEvent', (interaction: string) => {
console.log(interaction)
});
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Johna |
| Solution 2 | Ron Jonk |
