I have an Angular Service that defines a public Subject
. Later under some condition, the service will call .next()
on this Subject.
In addition, I have an Angular component that .subscribe()
to this Subject in it's ngOnInit()
method, and call .unsubscribe()
in it's ngOnDestroy()
method.
While both the service and the component are alive my code works fine. However, the user can click on a different tab in my app. Which cause my component to unload and call its ngOnDestroy()
method, meaning the Observable was unsubscribed.
Starting from this point, the component no longer exists however the service is still alive - other components still use it. When the service calling .next()
method after the component called .unsubscribe()
, this error is thrown ObjectUnsubscribedError.
ERROR Error: Uncaught (in promise): ObjectUnsubscribedError: object unsubscribed
In addition, later if the user goes back to the tab that contains the component, the ngOnInit()
is executed and the re-subscription to this observable throws the same error again.
What am I doing wrong, how can I resolve these errors?
import { Subject } from 'rxjs';
@Injectable({ providedIn: 'root' })
export class StatusService {
public statusChange$: Subject<number>;
public constructor(...) {
this.statusChange$ = new Subject<number>();
}
public someInternalLogic(someNumber: number): void {
this.statusChange$.next(someNumber);
// this will throw an error if StatusComponent call .unsubscribe()
}
}
@Component({
selector: 'app-status',
templateUrl: './status.component.html',
styleUrls: ['./status.component.scss']
})
export class StatusComponent implements OnInit, OnDestroy {
public constructor(
private _statusService: StatusService) {}
public ngOnInit(): void {
this._statusService.statusChange$.subscribe(value => this._onStatusChange(value));
}
public ngOnDestroy(): void {
this._statusService.statusChange$.unsubscribe();
// after this point if the StatusService calling .next() an error will be thrown
}
private _onStatusChange(value: number): void {
// ....
}
}
You don't need to unsubscribe service subject in component. Instead create an subscription variable for service subject in your component and unsubscribe it on component destroy
subscription!: Subscription;
public ngOnInit(): void {
this.subscription = this._statusService.statusChange$.subscribe(value => this._onStatusChange(value));
}
public ngOnDestroy(): void {
this.subscription.unsubscribe();
}
private _onStatusChange(value: number): void {
// ....
}