Angular Service singleton constructor called multiple times

14,014

As you have declared the TestService as -

@Injectable({
  providedIn: 'root'
})

Which means you are adding to AppRoot module.

No need to add explicitly in the CoreModule, so remove from providers of CoreModule. Remove following -

providers: [
    TestService
  ]

As you are adding the TestSevice in CoreModule which is already added in RootModule that's the reason it constructor getting called multiple times.

So use either of one from above.

Share:
14,014
daisura99
Author by

daisura99

Updated on June 13, 2022

Comments

  • daisura99
    daisura99 almost 2 years

    I am trying to use an app-wide service (UserService) that stores authenticated user details. I have set up some routes but found that UserService is instantiated per route. I want them to share the same UserService.

    I have created a CoreModule containing TestService as provider and imported it into AppModule.

    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 { }
    

    test.service.ts:

    import { Injectable } from '@angular/core';
    
    @Injectable({
      providedIn: 'root'
    })
    export class TestService {
      constructor() { console.log('testService constructor called');}
    }
    

    app.module.ts

    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 { }
    

    app-routing.module.ts

    import { NgModule } from '@angular/core';
    import { CommonModule } from '@angular/common';
    import { Routes, RouterModule } from '@angular/router';
    import { BasicLoginComponent } from './basic-login/basic-login.component';
    import { HttpClientModule } from '@angular/common/http';
    import { AdminComponent } from './layout/admin/admin.component';    
    
    const routes: Routes = [
      {
        path: '',
        component: AdminComponent,
        children: [
          {
            path: 'home',
            loadChildren: './dashboard/dashboard.module#DashboardModule'
          },
          {
            path: 'user/profile',
            loadChildren: './user-profile/user-profile.module#UserProfileModule'
          }
        ]
    
      },
    ]
    @NgModule({
      imports: [
        CommonModule,
        RouterModule.forRoot(routes),
        HttpClientModule
      ],
      exports: [
        [RouterModule]
      ],
      declarations: []
    })
    export class AppRoutingModule { }
    

    I have injected the TestService into DashboardComponent and UserProfileComponent constructors. However, when routing between two of these components, the TestService constructor is called twice.

    It seems so straightforward but somehow I can't get it right. Can anyone point me to the right direction to troubleshoot this?

    *edit

    dashboard.component.ts

    import {AfterViewInit, Component, OnInit, ViewEncapsulation} from '@angular/core';
    /*import {NotificationsService} from 'angular2-notifications';*/
    
    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) { // private servicePNotify: NotificationsService
      }
    
    
      ngOnInit() {
    
      }
    
    }
    

    user-profile-component.ts:

    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() {
    
      }
    
    }