Encountering the "Unrecognized teardown 1" error when subscribing to an Observable in Typescript and Angular2

Having trouble with using an Observable in my Angular2.rc.4 Typescript app. Check out the plunker for it here: https://embed.plnkr.co/UjcdCmN6hSkdKt27ezyI/

The issue revolves around a service that contains this code:

private messageSender : Observable<string>;

constructor() {
    this.messageSender = Observable.create(observer => this.clients.push(observer));
 }

public listenForMessages() : any {
    console.log("Listen Requested...")
    return this.messageSender;
}

I'm trying to listen to it from a component:

ngOnInit() {
    this.chatter.listenForMessages().subscribe(msg => console.log(msg));
}

This leads to the error below:

EXCEPTION: Error: Unrecognized teardown 1 added to Subscription.
Error: Unrecognized teardown 1 added to Subscription.
    at Subscriber.Subscription.add (Subscription.ts:151)
    at Observable.subscribe (Observable.ts:93)
    at LoginPage.ngOnInit (login.ts:15)
    at DebugAppView._View_LoginPage_Host0.detectChangesInternal (LoginPage.template.js:29)
    at DebugAppView.AppView.detectChanges (view.ts:261)
    at DebugAppView.detectChanges (view.ts:377)
    at DebugAppView.AppView.detectContentChildrenChanges (view.ts:280)
    at DebugAppView.AppView.detectChangesInternal (view.ts:272)
    at DebugAppView.AppView.detectChanges (view.ts:261)
    at DebugAppView.detectChanges (view.ts:377)
BrowserDomAdapter.logError @ browser_adapter.ts:82

After many hours of investigation, I have not found solutions on other sites. The error message originates from RxJS and is triggered when the object passed into .subscribe() method isn't recognized. Even passing lambdas or pre-defined functions results in the same issue.

Any insights? Creating the Observable in the component doesn't cause issues, but subscribing in the service triggers the error... Very perplexing situation.

Answer №1

If you encounter a similar error message, it may be due to not providing Object.create with a callback function that returns TeardownLogic. Here's the definition of TeardownLogic:

export type TeardownLogic = AnonymousSubscription | Function | void;

This is what an AnonymousSubscription interface looks like:

export interface AnonymousSubscription {
  unsubscribe(): void;
}

For instance, instead of returning a boolean like this:

this.showSomething = Observable.create((observer: Observer<boolean>) => this.code === "00108");

You should be returning an AnonymousSubscription like this:

this.showSomething = Observable.create((observer: Observer<boolean>) => {
    observer.next(this.code === "00108");
});

Answer №2

The main issue here is that when you use Array#push it returns a number, not an object or value related to TeardownLogic. This creates a problem in the code snippet

Observable.create(observer => this.clients.push(observer))
.

My recommendation would be to avoid the observer-array pattern altogether. It seems like trying to reinvent something that already exists and works well. This pattern has been seen in ng2 tutorials and honestly, it's not a good approach.

If you require multicast behavior, consider using a Subject instead:

private messageSender : Subject<string>;

constructor() {
    this.messageSender = new Subject<string>();
}

public listenForMessages() : any {
    console.log("Listen Requested...")
    return this.messageSender.asObservable();
}

A more efficient solution might involve eliminating the intermediate Subject entirely and subscribing directly to the message source. However, without further details about your application, it's difficult to provide specific guidance on how to achieve this.

Answer №3

Focusing on @Tom's response, I encountered a similar issue due to neglecting the Observer.

Incorrect Approach:

@Injectable()
export class QuizEditorGuard implements CanDeactivate<QuizEditorPage> {

  constructor(private app: ApplicationService) { }

  canDeactivate(
    quizEditor: QuizEditorPage,
    currentRoute: ActivatedRouteSnapshot,
    currentState: RouterStateSnapshot,
    nextState: RouterStateSnapshot
  ): Observable<boolean> | Promise<boolean> | boolean {
    return Observable.create((observer: Observer<boolean>) => {
      if (quizEditor && quizEditor.hasUnsavedChanges) {
        observer.next(true);
        observer.complete();
      }
      else
        return false; //issue lies here
    });
  }
}

Correct Approach:

@Injectable()
export class QuizEditorGuard implements CanDeactivate<QuizEditorPage> {

  constructor(private app: ApplicationService) { }

  canDeactivate(
    quizEditor: QuizEditorPage,
    currentRoute: ActivatedRouteSnapshot,
    currentState: RouterStateSnapshot,
    nextState: RouterStateSnapshot
  ): Observable<boolean> | Promise<boolean> | boolean {
    return Observable.create((observer: Observer<boolean>) => {
      if (quizEditor && quizEditor.hasUnsavedChanges) {
        observer.next(true);
        observer.complete();
      }
      else {
        observer.next(false); //always remember to notify the observer
        observer.complete();
      }
    });
  }
}

Referring back to @Steven's query, his issue arose from the same cause: He failed to instruct his object on how to proceed after inserting the client.

Observable.create(observer => 
    this.clients.push(observer));
    observer.next("some string");
    observer.complete();
 }

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

Mastering Data Labels in ng2-chart: A step-by-step guide

Once again, I find myself battling my Angular and JavaScript challenges, each question making me feel a little less intelligent. Let me walk you through how I got here. In my most recent project, I wanted to enhance the user experience by incorporating sl ...

Retrieving data from a database and displaying rows in a FormArray with Angular 5

As a newcomer to angular, I've created an event component where users can enter the event name along with details of packages. The functionality allows for creating multiple packages with the ability to add and remove rows using FormArray. While ever ...

Every time I attempt to execute an npm command, such as ng new, I encounter a "module not found" error despite having installed node version "v16.13.0"

https://i.stack.imgur.com/RBxyI.png node:internal/modules/cjs/loader:936 throw err; ^ Error: Cannot locate module 'C:\Program Files\nodejs\node_modules\npm\bin\node_modules\npm\bin\npm-cli.js' ...

Guide on importing a markdown file (.md) into a TypeScript project

I've been attempting to import readme files in TypeScript, but I keep encountering the error message "module not found." Here is my TypeScript code: import * as readme from "./README.md"; // I'm receiving an error saying module not found I als ...

Unable to resolve host name for registry.npmjs.org on port 80

Hello everyone! I'm currently working on getting my angular library published on npm, but I seem to be running into an issue. When I try to log in, I encounter the following error: npm ERR! code EAI_AGAIN npm ERR! errno EAI_AGAIN npm ERR! request to h ...

New Chrome update restricts insecure cookies from functioning in Angular

We have been utilizing the ngx-cookie-service to establish session cookies for our logged-in users. Everything was functioning properly until yesterday when the latest Chrome update began blocking unsecure cookies and displaying a warning message in the co ...

Setting a custom port for your Node.js Typescript project on Heroku

In the usual case, Heroku dynamically assigns a port for us. const PORT : string|number = process.env.PORT || 5000; However, how can I alter this code to handle the PORT... utilizing the => TypeScript shorthand? server.listen(port => { console.l ...

Developing a Generic API Invocation Function

I'm currently working on a function that has the capability to call multiple APIs while providing strong typing for each parameter: api - which represents the name of the API, route - the specific route within the 'api', and params - a JSON ...

Merge two RxJS Observables/Subscriptions and loop through their data

Working with Angular (Version 7) and RxJS, I am making two API calls which return observables that I subscribe to. Now, the challenge is combining these subscriptions as the data from both observables are interdependent. This is necessary to implement cer ...

Leveraging the power of Kendo UI for Angular, bind the click event of a kendoButton to a method associated with a variable within

I have a variable called "message" in my component that is of type "any" and contains a method named "actionnowrapper()". When I bind this method to a regular HTML button like so, everything works as expected. <button (click)="message.actionnowrapper( ...

Issue with installing firebase-tools through macOS terminal

Having trouble installing firebase-tool for CLI on macOS. Attempts to install using $ sudo npm install -g firebase-tools are resulting in failures. I encountered errors related to permission denied when trying to access directories even with 'sudo&a ...

Calling the ngSubmit.emit() function does not alter the submitted property within the formGroup

When dealing with two forms that require validation before being shown to the user, the challenge lies in triggering the submission of both forms simultaneously. This ensures that only the required fields are displayed for the user to fill out. Currently, ...

Angular app experiences a breakdown due to a JitCompiler issue

After being given the responsibility of enhancing a project, I diligently added new modules and components. However, upon running the application, it crashes. Uncaught Error: Component EnquiryComponent is not part of any NgModule or the module has not bee ...

What is the best way to include multiple targets/executables within a single Node.js repository?

My React Native app is developed using TypeScript, and I want to create CLI tools for developers and 'back office' staff also in TypeScript. These tools should be part of the same monorepo. After attempting to do this by creating a subfolder wit ...

What is the best way to send various parameters to a component using [routerLink] or router.navigate?

My app-routing.module.ts is configured as shown below: const routes: Routes = [ { path: "branches/:branch", component: BranchesComponent }, // ... ]; In addition, in my app.component.html, I have the following code: <li> ...

Tips for selecting the best className type for material-ui components

Currently, I am integrating material-ui into a react app that is built using typescript. Within the material-ui framework, there is a feature called withStyles which allows styles to be injected into a component through its className. However, I am facing ...

Tips for finalizing a subscriber after a for loop finishes?

When you send a GET request to , you will receive the repositories owned by the user benawad. However, GitHub limits the number of repositories returned to 30. The user benawad currently has 246 repositories as of today (14/08/2021). In order to workarou ...

While attempting to utilize npm install, I encounter an error on a discord bot stating "msvsVersion is not defined."

Struggling with self-hosting a TypeScript discord bot, the setup process has been a puzzle. It's supposed to generate a build directory with an index.js file, but it's unclear. Installed Visual Studio Build Tools 2017 as required, yet running npm ...

Counting up in Angular from a starting number of seconds on a timer

Is there a way to create a countup timer in Angular starting from a specific number of seconds? Also, I would like the format to be displayed as hh:mm:ss if possible. I attempted to accomplish this by utilizing the getAlarmDuration function within the tem ...

Encountering the identical error message while attempting to execute my application: "Uncaught TypeError: this.microservicesModule.register is not a function."

Despite my repeated attempts to run the application, I am consistently encountering the following error message: "UnhandledPromiseRejectionWarning: TypeError: this.microservicesModule.register is not a function at NestApplication.registerModules ...