ObjectUnsubscribedError when trying to prevent subscribing twice
Solution 1
I would get the subscription and unsubscribe on it this way and not on the subject directly:
ngOnInit() {
this.pages$ = this.pagesService.getPagesListener();
this.subscription = this.pages$.subscribe((pages) => { // <-------
this.pages = pages; console.log(pages);
});
this.pagesService.getAll();
}
ngOnDestroy() {
this.subscription.unsubscribe(); // <-------
}
Solution 2
.subscribe() returns a Subscription
- You should use this to unsubscribe
e.g.
Parent has a reloadSubject: Subject;
- child1 -> subscribes
- child2 -> subscribes
child1 - "WORKS" -> unsubscribe's his subscription
ngOnInit{
sub: Subscription = parent.subscribe();
}
onDestroy{
this.sub.unsubscribe();
}
child2 - "DOES NOT WORK" -> unsubscribe's the whole parent
ngOnInit{
parent.subscribe();
}
onDestroy{
parent.unsubscribe();
}
If you call unsubscribe on the parent both children are gone.
If you unsubscribe the Subscription that you get from the .subscribe()
then only one child is unsubscribed.
Please correct me if I am wrong!
AlvYuste
Fullstack and UX developer, Javascript passionate. Currently programming with React, NodeJS and Mongo.
Updated on November 17, 2020Comments
-
AlvYuste over 3 years
I have a Service and a component that uses it:
PagesService
PagesListComponent
In the
PagesService
I have an array ofPages
. I notify changes in the array via aBehaviorSubject
which both of them are subscribed to.The
PagesService
are provided atbootstrap
, to have just one instance shared. That's because I need to keep the array, instead of downloading the pages everytime they are needed.The code is the following:
pages.service.ts
import { Injectable } from '@angular/core'; import { BehaviorSubject } from 'rxjs/Rx'; import { Http, Response } from '@angular/http'; import { Page } from './../models/page'; @Injectable() export class PagesService { public pages$: BehaviorSubject<Page[]> = new BehaviorSubject<Page[]>([]); private pages: Page[] = []; constructor(private http: Http) { } getPagesListener() { return this.pages$; } getAll() { this.http.get('/mockups/pages.json').map((res: Response) => res.json()).subscribe( res => { this.resetPagesFromJson(res); }, err => { console.log('Pages could not be fetched'); } ); } private resetPagesFromJson(pagesArr: Array<any>) { // Parses de Array<any> and creates an Array<Page> this.pages$.next(this.pages); } }
pages_list.component.ts
import { Component, OnInit } from '@angular/core'; import { Router } from '@angular/router-deprecated'; import { BehaviorSubject } from 'rxjs/Rx'; import { PagesService } from '../../shared/services/pages.service'; import { GoPage } from '../../shared/models/page'; @Component({ moduleId: module.id, selector: 'go-pages-list', templateUrl: 'pages_list.component.html', styleUrls: ['pages_list.component.css'] }) export class PagesListComponent implements OnInit { pages$: BehaviorSubject<GoPage[]>; pages: GoPage[]; constructor(private pagesService: PagesService, private router: Router) { } ngOnInit() { this.pages$ = this.pagesService.getPagesListener(); this.pages$.subscribe((pages) => { this.pages = pages; console.log(pages) }); this.pagesService.getAll(); } ngOnDestroy() { this.pages$.unsubscribe(); } }
This works fine the first time, both the subscription onInit and de unsubscription onDestroy. But when I return to the list and try to subscribe again (to fetch the current value of pages[] and listen for future changes), it fires the error
EXCEPTION: ObjectUnsubscribedError
.If I don't unsubscribe, everytime I enter to the list, a new subscription is stacked, and all of them are fired when a next() is received.