Endless cycle encountered while handling error from BehaviorSubject subscribed to by asynchronous pipeline in Angular 2

I am facing an issue with my rxjs BehaviorSubject in Angular 2. I am subscribing to it using an async pipe and handling errors with a catch block. However, I am stuck in an infinite loop every time an error occurs. This is because my catch block returns the Observable from the BehaviorSubject, causing the async pipe to resubscribe to the observable.

Here is a simplified version of the code:

ListService - an @Injectable class that contains the BehaviorSubject and the property with the Observable.

private listSubject: BehaviorSubject<IItem[]>;

public get listObservable() {
    return this.listSubject.asObservable()
}

private error(error: IError) {
    this.listSubject.error(error);
}

ListComponent - a @Component that displays the list observable.

// Template
<items-view [items]="list | async"></items-view>

// Code
public get list() {
    return this.listService.listObservable
        .catch((error) => {
            this.handleError(error);
            return this.listService.listObservable;
        });
}

The issue arises because my catch block returns the current observable, which causes an endless loop. I have tried returning a cached array in the error to return an Observable.of(error.cached), but it resulted in other problems as the async pipe seemed to lose its subscription to the BehaviorSubject.

I have tried different solutions but have been unable to break out of the infinite loop. Any help would be greatly appreciated.

Thank you in advance.

Answer №1

Manually triggering an error on a Subject, especially one like a BehaviorSubject, is generally not a good idea. When an error occurs on a Subject, it essentially becomes inactive, meaning no new data can be emitted from it. This concept is fundamental in rxjs. Here's a simple example:

let stream$ = new Rx.BehaviorSubject(1);

stream$.subscribe(x => console.log("Logging: " + x), e => console.error("Error: " + e)); // logs 1, 2, Error: ...

stream$.next(2);
stream$.error(new Error("Some error message."));
stream$.next(3); // this won't work because the stream is "dead"
stream$.subscribe(x => console.log("Logging 2: " + x), e => console.error("Error: " + e)); // only logs the error

In your case, returning the "old, dead, error"-Subject after handling the error propagates the error down the stream. It's important to use .error only for streams with defined operations and results, not on Subjects meant to emit data throughout the application's lifespan.

A solution for your case could involve using separate Subjects for data and errors, or restructuring your architecture into data generation and data storage parts.

How to Handle Errors:

  1. Event Occurs
  2. Call Service to Generate or Fetch Data with Error Handling
  3. Emit Data with .next or Handle Errors

Subscription:

  1. UI Subscribes to Data Subject
  2. Automatically Updates on New Data, No Error Handling Needed

Consider implementing a store architecture like ngrx for a more structured approach, though this may require significant refactoring in existing projects.

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

Encountering an ERROR with the message "Error: NG0100: ExpressionChangedAfterItHasBeenCheckedError" while attempting to apply a filter to

My mat table includes a filter that utilizes chips to sort by multiple criteria. Upon my initial attempt to filter and save the criteria, I encountered an error called ExpressionChangedAfterItHasBeenCheckedError. The error message indicates a transition f ...

After the component has been initialized for the second time, the elementId is found to be null

When working with a component that involves drawing a canvas chart, I encountered an issue. Upon initializing the component for the first time, everything works fine. However, if I navigate away from the component and return to it later, document.getElemen ...

Solving Circular Dependencies in React with TypeScript by using smart importing techniques

I've set up a union type in the parent component export type Students = "fresher" | "secondYear" | 'finalYear' | 'postGrad'; A circular dependency is causing issues, and the most obvious solution is to define ...

What could be the reason it's not functioning as expected? Maybe something to do with T extending a Record with symbols mapped

type Check<S extends Record<unique, unknown>> = S; type Output = Check<{ b: number; }>; By defining S extends Record<unique, unknown>, the Check function only accepts objects with unique keys. So why does Check<{b:number}> ...

Issue encountered during rendering: "TypeError: Attempting to access property '_t' of an undefined object" while running a Unit Test using Jest

I spent hours troubleshooting a unit test for my Vue.js component, but no matter how much I searched the internet, I kept encountering this error: console.error node_modules/vue/dist/vue.runtime.common.dev.js:1884 TypeError: Cannot read property ' ...

The header code in Angular 6 does not get triggered when working with the router

After successfully validating the username and password, I perform the following action: this.router.navigate(['./home']); Each page includes a header with the following content: <ng-container *ngIf='isAuthenticated'> <li c ...

Connecting Angular components to the Document Object Model (DOM)

In previous versions of AngularJS, you could create a directive and link it to an existing controller, allowing you to use the same controller for multiple directives with different templates. angular .module('App') .component('Name', ...

File handling in Angular 2 using Typescript involves understanding the fundamental syntax for managing files

Would someone be able to explain the fundamental syntax for reading and writing text files, also known as file handling in TypeScript? If there is a corresponding link that anyone could provide, it would be greatly appreciated. ...

Steps for compiling SCSS to CSS using Angular-CLI and moving it to the assets directory

I am currently working on an Angular 5 project with an assets folder where I store my common CSS file and reference it in index.html. I now plan to create a new folder called "sasstyles" and place some .scss files there. When I compile or run the project ...

What is the best way to include a background image in an Angular selector?

I'm having trouble setting a background image for an Angular selector. Here's the code I'm using: <app-highway-card [ngStyle]="{'background-image':'url(https://cdn.pixabay.com/photo/2021/09/04/09/32/road-6597404__340.j ...

Setting up Webpack for Node applications

My current challenge involves configuring Webpack for a node app that already exists. I am encountering various issues and struggling to find solutions or even know where to begin. Situation The project's folder structure is as follows: +---app +-- ...

Directing non-www to www in Next.js has never been easier

Based on the information I've gathered, it seems that using www is more effective than not using it. I am interested in redirecting all non-www requests to www. I am considering adding this functionality either in the next.config.js file or, if that& ...

When there is data present in tsconfig.json, Visual Studio Code does not display errors inline for TypeScript

After creating an empty .tsconfig file (consisting solely of "{ }"), Visual Studio Code immediately displays errors both inline and in the "problems" section. Interestingly, when I populate the tsconfig.json file with data, these errors disappear. Is there ...

Ways to activate form submission from two buttons with a single event in Angular

In my current setup, I have a form component along with two buttons: <ui-form (submit)="..."></ui-form> <button (click)="save()">save</button> <button (click)="open()">open</button> The cha ...

ng-show directive in AngularJS is not functioning properly when utilized with CLI

After setting up my Angular app with ng new app, I attempted to hide certain elements conditionally using ng-show. Unfortunately, it doesn't seem to be working as expected. <span ng-show="false">Angular App</span> Regardless ...

Step-by-step guide on how to stop CDK Drop depending on a certain condition

I'm trying to figure out how to disable dropping using CDK based on certain conditions. Specifically, I want the drop functionality to be disabled if the list I'm attempting to drop into is empty. I haven't been able to find a solution withi ...

NgbHighlight now allows for one highlight element per line

I am currently utilizing NgbHighlight to allow users to search within a list. However, I am facing an issue with the highlighting of search results. My intention is to highlight only the first match in the list. I am sticking to the basic implementation ...

Encountering issues with Next.js routing - Pages failing to load as expected

Having some trouble with the routing in my Next.js application. I've created a page named about.tsx within the "pages" directory, but when trying to access it via its URL (localhost:3000/about), the page fails to load correctly and displays: This Pa ...

Dividing the text by its position value and adding it to a fresh object

I needed to divide the paragraph into sections based on its entityRanges. Here is what the original paragraph looks like: { type: 'paragraph', depth: 1, text: 'Do you have questions or comments and do you wish to contact ABC? P ...

Using RadSideDrawer with Typescript in Vue class components: A Step-by-Step Guide

I am attempting to integrate external components into Vue Typescript Class Components. Following the installation of the standard template, I made modifications to its <script> block based on this guide: import { Vue, Component, Prop } from "vue-pro ...