Angular Service singleton constructor being invoked multiple times

I have been facing an issue with using an app-wide service called UserService to store authenticated user details. The problem is that UserService is being instantiated per route rather than shared across routes. To address this, I decided to create a CoreModule containing TestService as a provider and imported it into the AppModule.

Here's how I set up the CoreModule in `core.module.ts`:

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { TestService } from '../test.service';

@NgModule({
  imports: [
    CommonModule
  ],
  declarations: [],
  providers: [
    TestService
  ]
})
export class CoreModule { }

The TestService itself looks like this in `test.service.ts`:

import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class TestService {
  constructor() { console.log('The testService constructor has been called');}
}

Within my `app.module.ts`, I made sure to import the CoreModule along with other necessary modules:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { AdminComponent } from './layout/admin/admin.component';
import { AppComponent } from './app.component';
import { AppRoutingModule } from './app-routing.module';


import { CoreModule } from './core/core.module';

@NgModule({
  declarations: [
    AppComponent,
    AdminComponent,
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    FormsModule,
    CoreModule
  ],
  providers: [
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

Even though I injected TestService into DashboardComponent and UserProfileComponent constructors, I noticed that the TestService constructor was called twice when routing between these components. I'm struggling to figure out where I might be going wrong. Can anyone provide some guidance on how to troubleshoot this issue?

*edit

In the `dashboard.component.ts` file:

import {AfterViewInit, Component, OnInit, ViewEncapsulation} from '@angular/core';

import { UserService } from '../user.service.js';
import { LocalStorageService } from '../../../node_modules/ngx-webstorage';
import { TestService } from '../test.service.js';

@Component({
  selector: 'app-dashboard',
  templateUrl: './dashboard.component.html',
  styleUrls: ['./dashboard.component.scss'],
  encapsulation: ViewEncapsulation.None
})
export class DashboardComponent implements OnInit, AfterViewInit {


  constructor(private userService:UserService, private localSt:LocalStorageService,
  private testService:TestService) {}
  
  ngOnInit() {}

}

And in the `user-profile-component.ts` file:

import {Component, OnInit} from '@angular/core';
import {animate, style, transition, trigger} from '@angular/animations';
import {Http} from '@angular/http';
import { TestService } from '../test.service';

@Component({
  selector: 'app-user-profile',
  templateUrl: './user-profile.component.html',
  styleUrls: ['./user-profile.component.scss', '../../assets/icon/icofont/css/icofont.scss']
})
export class UserProfileComponent implements OnInit {

  constructor(public http: Http, private userService: UserService, private testService:TestService) {}

  ngOnInit() {}

}

Answer №1

When declaring the TestService as follows -

@Injectable({
  providedIn: 'root'
})

This indicates that you are adding it to the AppRoot module.

There is no need to explicitly add it in the CoreModule, so remove it from the providers of the CoreModule. Remove the following snippet -

providers: [
    TestService
  ]

Since you have added the TestSevice in the CoreModule which is already included in the RootModule, this causes the constructor to be called multiple times.

Therefore, choose one of the options mentioned above.

Answer №2

@Injectable({
  providedIn: 'root'
})

  • When using the providedIn option with root, the service becomes a singleton available throughout the application.
  • You won't encounter any errors like No provider for xxxservice due to the use of providedIn if you forget to add it to the providers list of any module.
  • Adding it to the list will result in a new instance of the service being created, leading to unexpected outcomes.

Remember: Utilize this concept for optimal results.

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

Execute various Office Scripts functions within a single script based on the button that is selected

Imagine you have an Excel spreadsheet with two buttons named populate-current and populate-all. Both buttons execute the same Office Script function that looks something like this: function populateByRowIndex(workbook: ExcelScript.Workbook, rowIndex: numbe ...

Having trouble importing the d3-geo package into a Node.js TypeScript project

Seeking a way to test the inclusion of specific latitude and longitude coordinates within different GeoJSON Features using code. When attempting this with: import d3 from 'd3-geo'; // or: import * as d3 from 'd3-geo' // no difference ...

Is there a way to turn off the "defer" feature in an Angular build?

After compiling my Angular project, I noticed that the compiler automatically adds the "defer" attribute to the script tag in my "index.html" file. However, I need to disable this feature. Is there a way to do it? I am currently working with Angular versi ...

Is there a way to change routerLink to href?

I am struggling with converting routerLink to href. <a [routerLink]="['/choose',{id:sizzle.parameter,type:dish}]" I attempted it, but I keep getting an error <a [href]="'/choose'+id:sizzle.parameter+type:dish" ...

When should services be included within providers?

After completing a small Angular 2 project, I compared my work with the provided code and realized that in the app.module.ts file, only one of the two services I created was included by the tutor. users.service.ts import { Component, Injectable } fro ...

Obtain characteristics of the primary element in Ionic version 2 or 3

After creating and opening my Sqlite database and saving the SQLiteObject in a variable within my app.component.ts, I now need to retrieve these attributes in my custom ORM. The ORM extends to other providers to describe the title and field of my tables. ...

Django-oauth2 encountered a 500 error due to the presence of unauthorized URL query parameters in the request

Just starting out with django. Using: oAuth2 + PKCE protocol, Angular, Django-oauth2-toolkit + REST Continuously receiving this error: oauthlib.oauth2.rfc6749.errors.InvalidRequestError: (invalid_request) URL query parameters are not allowed <oauthli ...

"Would someone be able to advise me on how to correctly reference the PrimeNG AutoCompleteModule within my

I've been developing an application that relies on auto-complete functionality. To begin, I installed some available templates using the dotnet command line tool and then selected a template directory before installing the Angular template. dotnet ne ...

Distribute among an array of specific types

I am trying to achieve this behavior using Typescript: type animals = 'cat' | 'dog' let selectedAnimals: animals[] = ['cat'] selectedAnimals = [ // <- Type 'string[]' is not assignable to type 'animals[]&ap ...

Having trouble getting my Angular 2 project up and running

After downloading a MEAN stack project from bitbucket, I attempted to run the front end (Angular 2) locally by navigating to the angular folder and using the command ng serve. However, I encountered the following error: "The serve command requires to be ...

Typescript implements strict enforcement of partial interfaces

In my application, I am working with JSON data. Here is a simplified example: data { prop1: "abc", prop2: 123, COL_A12: "mydata", COL_A13: "myotherdata", } I am aware that the data will consist of multiple prop1 and prop2 properties. However, CO ...

What is the process for importing the Scale type definition from the Scale module?

Recently, I've been utilizing the Tonal package within a Vite/Vue/Typescript project. My current task involves importing the type known as Scale from the Scale module. You can find the type definition here: export interface Scale extends ScaleType { ...

Challenges encountered when testing middleware in a TypeScript Node.js Express project

I have been exploring the repository at https://github.com/goldbergyoni/nodebestpractices to enhance my understanding of nodejs best practices. Below is a middleware I developed: import { NextFunction, Request, Response } from "express"; import ...

Declaring a sophisticated array as a property within another property in Typescript

As a newcomer to Angular and Typescript, I am facing a challenge while declaring a property with a complex array as one of its values. Here is what I have attempted: groupedItem: { customGroupId: string, cgName: string, category: [{ cu ...

Encountering a issue while running npm start with Angular 2 RC build

After upgrading from Angular2 beta 15 to the RC version, I encountered some errors while trying to run my application. typings/browser/ambient/es6-shim/index.d.ts(8,14): error TS2300: Duplicate identifier 'PropertyKey'. typings/browser/ambient/e ...

What exactly does the question mark represent in the code structure as indicated in VSCode?

When looking at the image, you can see that in the description of done(), VSCode indicates the type of parameters using a colon error: any or sometimes with a question mark and colon user?: any. So, what exactly is the distinction between these two ways o ...

Troubleshooting issues with Docker and Angular 2: unable to retrieve data

We are in the process of setting up an Angular 2 application with Docker by following a tutorial available at: https://scotch.io/tutorials/create-a-mean-app-with-angular-2-and-docker-compose Although the application deploys successfully, we encounter an i ...

Convert JSON data to an array using Observable

My current task involves parsing JSON Data from an API and organizing it into separate arrays. The data is structured as follows: [ {"MONTH":9,"YEAR":2015,"SUMAMT":0}, {"MONTH":10,"YEAR":2015,"SUMAMT":11446.5}, {"MONTH":11,"YEAR":2015,"SUMAMT":5392 ...

Transform the code provided by bundleMDX into an HTML string specifically for RSS, all the while utilizing the mdx-bundler

I am currently working on developing an RSS reader and I need to convert the code returned by bundleMDX into a string. This is necessary so that I can utilize it with ReactDOMServer.renderToStaticMarkup(mdx) in my project. You can find a similar implement ...

Angular 2 decorators grant access to private class members

Take a look at this piece of code: export class Character { constructor(private id: number, private name: string) {} } @Component({ selector: 'my-app', template: '<h1>{{title}}</h1><h2>{{character.name}} detai ...