1

I am new to Angular and am trying to figure out how to inject my Angular service (game service) into another angular service which will be a Resolver (game resolver). Only one instance of my game service is typically created in my application and I am injecting it into each of my components successfully, but when my game resolver service is needed, it creates a new instance of the game service, even though the game service is supposed to be a singleton.

I've tried declaring both services in the 'providers' array of my NgModule, to try to make them both singleton services and I've also tried the approach of of declaring 'providedIn: 'root' in the @Injectable decorator, but a new instance of the game service is created when the game resolver service constructor is called.

//GameResolver.service.ts

    @Injectable({
      providedIn: 'root'
    })
    export class GameResolverService implements Resolve<Game> {
      constructor(private gameService: GameService) {

      }


      resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<Game> {

          return this.gameService.getGameById(gameId)

      }
    }

//game-resolver.service.spec.ts    

import { TestBed, inject } from '@angular/core/testing';

import { GameResolverService } from './game-resolver.service';

describe('GameResolverService', () => {
  beforeEach(() => {
    TestBed.configureTestingModule({
      providers: [GameResolverService]
    });
  });

  it('should be created', inject([GameResolverService], (service: GameResolverService) => {
    expect(service).toBeTruthy();
  }));
});



//Game.service.ts

import { Injectable } from '@angular/core';
import { Http, Headers } from '@angular/http';
import { Game } from './game';
import { map } from "rxjs/operators";
import { User } from './user';


@Injectable({
  providedIn: 'root'
})
export class GameService {

  constructor(private http: Http) {
    console.log('new instance of GameService created');
  }



//app.module.ts

const appRoutes: Routes = [
  ...
  {path:'game', component: GameComponent, data:{depth:3}, resolve: { game: GameResolverService}},
  {path:'endGame', component: EndGameComponent, data:{depth:4}},
  {path:'nextRound', component: NextRoundComponent, data:{depth:5}}
]

@NgModule({
  declarations: [
    ...
  ],
  imports: [
    ...
  ],
  bootstrap: [AppComponent],
  providers: [GameService, GameResolverService]
})


//create-game.component.ts
...
import {GameService} from '../game.service';




@Component({
  selector: 'app-create-game',
  templateUrl: './create-game.component.html',
  styleUrls: ['./create-game.component.css'],

})
export class CreateGameComponent implements OnInit {
  // @HostListener('window:popstate', ['$event'])




  constructor(private gameService: GameService, private router: Router) {
   }


//game.component.ts

@Component({
  selector: 'app-game',
  templateUrl: './game.component.html',
  styleUrls: ['./game.component.css']
})
export class GameComponent implements OnInit {

  game:Game;

  constructor(private gameService: GameService, private router: Router, private socketService: SocketService, private route: ActivatedRoute ) {
    this.game = this.route.snapshot.data['game']
  }
}

Is there something I'm not understanding about the hierarchy of angular dependency injection? I need the GameService to be a singleton service across all parts of the app, so I need the singleton instance to be injected in the Game Resolver Service without creating a new instance.

11
  • Possible duplicate of How do I create a singleton service in Angular 2? Commented Jan 28, 2019 at 22:15
  • 2
    You should either have providedIn: 'root' in the services themselves or add them as part of the providers array in the module, not both. Commented Jan 28, 2019 at 22:27
  • @DzhavatUshev Thanks for pointing that out to me. I am still getting multiple GameService instances when implementing either choice however. Commented Jan 28, 2019 at 22:42
  • What do you mean by multiple instances? Try injecting the GameService into another service and/or component and see whether the constructor runs? Commented Jan 28, 2019 at 22:49
  • What I mean is that when GameService is injected into a Component, the GameService constructor is NOT called. But when it is injected into the GameResolverService, the GameService constructor is called. Commented Jan 28, 2019 at 22:57

1 Answer 1

3

I finally realized after much searching that in my app.component.ts file, I still had the providers array defined in the @Component decorator, while I was using the providedIn: 'root' method. Dzhavat Ushev was right, you cannot use both of these at the same time. I thought I had gotten rid of all my providers declarations, but I had no idea that one was there. It works perfectly now. Thanks for you help guys.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.