Error encountered when attempting to prevent a duplicate subscription by throwing an ObjectUnsubscribedError

I am dealing with a Service and a component that utilizes it:

  • PagesService
  • PagesListComponent

Within the PagesService, there exists an array of Pages. Updates to this array are communicated via a BehaviorSubject that both components subscribe to.

The PagesService is provided at bootstrap in order to have a single shared instance. This is necessary to maintain the array without having to download pages every time they are needed.

The code setup is as follows:

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>) {
        // Parsing the Array<any> and creating 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 implementation works well initially, with subscription onInit and unsubscription onDestroy. However, upon attempting to re-subscribe when returning to the list (to fetch the current value of pages[] and listen for future changes), it results in an error being thrown -

EXCEPTION: ObjectUnsubscribedError
.

If I omit the unsubscribe method, a new subscription is stacked each time I enter the list, causing all of them to trigger when next() is received.

Answer №1

To manage the subscription effectively, I recommend utilizing the following approach instead of unsubscribing directly:

ngOnInit() {
  this.articles$ = this.articlesService.getArticlesListener();
  this.subscription = this.articles$.subscribe((articles) => { // <-------
    this.articles = articles; console.log(articles);
  });
  this.articlesService.getAll();
}

ngOnDestroy() {
    this.subscription.unsubscribe(); // <-------
}

Answer №2

When you use .subscribe(), it returns a Subscription.

  • This is important for unsubscribing later on


For example, the parent component has a reloadSubject: Subject;

  • child1 -> subscribes
  • child2 -> subscribes

child1 - "WORKS" -> unsubscribes from his subscription

ngOnInit{ 
  sub: Subscription = parent.subscribe();
}
onDestroy{
  this.sub.unsubscribe();
}


child2 - "DOES NOT WORK" -> mistakenly unsubscribes the whole parent

ngOnInit{ 
  parent.subscribe();
}

onDestroy{
  parent.unsubscribe();
}

If you call unsubscribe on the parent, both children are removed.
But if you unsubscribe the individual Subscription obtained from .subscribe(), only one child is unsubscribed.

Feel free to correct me if I'm mistaken!

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The callback function was called twice after making a POST request

I am encountering an issue with my TypeScript code for processing Spotify's login flow. The code snippet is structured as follows: import * as React from 'react'; import '@patternfly/react-core/dist/styles/base.css'; import { useNa ...

A specialized wrapper for push notifications in Cordova that utilizes observables for streamlined

When working with the phonegap-plugin-push for cordova, you will come across various functions that use the following syntax: function name(successCallback(),errorCallback(),options) I am interested in creating a wrapper function that returns an Observab ...

Angular Validators are behaving inconsistently, as they only work intermittently before stopping altogether once the application is

Why does my code sometimes behave differently after running for a while and then return to normal after restarting the Angular server without making any changes?The pop-up that says "please fill out this field" disappears when it shouldn't This is th ...

Separating HTML content and text from a JSON response for versatile use within various sections of an Angular 2 application using Typescript

Hello there! I am currently utilizing Angular 2 on the frontend with a WordPress REST API backend. I'm receiving a JSON response from the service, however, the WP rest API sends the content with HTML tags and images embedded. I'm having trouble s ...

Refining search results with dynamic filter conditions in TypeScript array objects and using search refiners in SharePoint

In my Typescript and SharePoint Search project, I am working on a scenario involving a Collection of Arrays structured as follows: let _SelectedBusinessUnits =[ { "fileName": "XYX.doc", "Region": "APAC", "Country":"Australia;China", "LOB": "Auto;Busines ...

Exclusive Vue3 Props that cannot be used together

How can a component be created that accepts either json with jsonParserRules or jsonUrl with jsonParserRulesUrl, but not both? It would be ideal if the IDE could provide a warning when both props are specified. Example of an Attempt that does not Work < ...

Typescript throws an error when attempting to return an array of strings or undefined from a function

I created a shallow differences function that compares two arrays of strings and returns either undefined (if the arrays are different lengths) or a string array containing matching characters at corresponding indexes. If the characters don't match, i ...

Including .d.ts files in TypeScript files

I am facing an issue with importing types from a .d.ts file that I created. The TypeScript compiler is giving an error related to the file path, displaying this message: File '.../lib/types/generated.d.ts' is not a module.ts(2306) The error occu ...

Tips on customizing a row in a table

Having a small issue styling a row in my table. Essentially, the table consists of 4 rows. a) If the data under column Title 5 is below 0, then the entire row should display in red color. b) If the data under column Title 5 is equal to 17, then the compl ...

Angular: Trigger service call upon onBlur event of input changes

In Angular, I am looking to detect any changes in the text input during the onBlur event and then take specific actions accordingly: Criteria for processing during the onBlur event: Only proceed if there has been a change in the text input. If the input ...

Harness - Utilize secretive environment variables in Typescript to enhance Google Apps Script development

Are there any solutions available to avoid embedding secrets directly into a Google Apps Script project? I am utilizing clasp and coding in Typescript following the instructions outlined in this guide. At the moment, my script (Main.ts) contains hardcode ...

Why is my Angular app displaying outdated data from Firebase when navigating between pages?

Currently, I am dealing with an Angular 9 application that is hosted on Firebase and utilizes Firestore for its data storage. There is a perplexing issue that I haven't been able to figure out completely despite simplifying the app extensively. I will ...

There is no overload match for the HttpClient.get call at this time

I'm trying to set up a file download feature using a blob, but I need to extract the filename from the server's "content-disposition" header. Here's the code I have: const header = {Authorization: 'Bearer ' + token}; const config ...

The Extended Date type is indicating that the function cannot be located

I came across this helpful gist with date extensions: https://gist.github.com/weslleih/b6e7628416a052963349494747aed659 However, when attempting to use the functions, I encountered a runtime error stating: TypeError: x.isToday is not a function I foun ...

I am in need of assistance with incorporating a particular hibernate Inheritance mapping into my project

I am dealing with a situation where I have two classes, parent and child, with a self-referential relationship on the child side. The database is set up with separate tables for both parent and child, sharing the same "id", and using the column "holder" as ...

Enhance User Experience in Chat Screen: Maintain Automatic Scroll to Bottom with Components of Variable Height in Ionic 6

In my Angular Ionic 6 application, I have a chat screen that I want to automatically scroll to the bottom when it loads. Although I know how to achieve this using this.ionContent.scrollToBottom();, I'm facing an issue with some messages containing dy ...

I am looking to modify a particular value within an array of objects, but for some reason, the update is not being applied correctly

When attempting to copy the array, I update the selected value of a specific object based on the matching memberId. This process works well for a single member, however, issues arise when there are multiple members as the updating doesn't work correct ...

What causes BehaviorSubjects in Angular RXJS to emit multiple values?

click here to see the image descriptionUsing BehaviorSubject for sharing data between components in my app has led to a performance problem caused by multiple emissions of the same value. For example, when I make an HTTP call to fetch a team object from th ...

When employing the pipe function within *ngFor, the webpage's refresh may vary, causing occasional updates

Utilizing angular2-meteor, I have already implemented pure: false. However, the pipe seems to be running inconsistently. For more details on the issue, please refer to my comments within the code. Thank you. <div *ngFor="#user of (users|orderByStatus) ...

Construct the output directory according to the specific environment

I'm exploring the process of constructing and launching an Angular 2 project using angular cli with variables specified in my environment typescript files. For instance, within my angular-cli.json file, there is a dev environment linked to "environme ...