Search code examples
angularserviceconstructorinitializationngoninit

Should I initialise an Angular service in its constructor or in the ngOnInit method of the app.component?


I'm new to Angular. I have a service that needs to subscribe to a subject provided by another service. If this was a component, I would create the subscription in the ngOnInit method of the component. NgOnInit isn't called for Services, though. I have created an initialise method to create the subscription but I'm not sure where best to call it from. I have seen it done two ways:

1) Call the initialise method in the service constructor

2) Inject the service into the app.component and call the service initialise method in the app.component's ngOnInit method e.g.

method 1:

export class MyService{

    constructor(private myRequiredService: RequiredService) {
        this.initialiseSubs();
    }

    initaliseSubs(){
        //code to set up subscriptions
    }
}

Method 2


export class MyService{

    constructor(private myRequiredService: RequiredService) {}

    initaliseSubs(){
        //code to set up subscriptions
    }
}

export class AppComponent implements OnInit{
  title = 'my-app';

  constructor(private myService:MyService){}

  ngOnInit(){
    this.myService.initialiseSubs();

  }
}

Both methods seem to work but I would welcome advice as to which is preferable. Thanks in advance.


Solution

  • The service is the place where you define your observables, e.g. getAllEmployees(). The components are the place where you use those services; e.g. by injecting them into the constructor).

        export class MyService{
        
            constructor(private myRequiredService: RequiredService) {}
        
            getAllEmployees():Observable<Employee[]>{
               
               // return Observables of type Employee[]
            }
        }
    

    Suppose now you have a component called EmployeesList, which is responsible for showing all the employees data. Firstly, you need to inject the service into the constructor. Next, you call the getAllEmployees service method and subscribe in order to to produce a result "aka data".

        import { Component, OnInit } from '@angular/core';
        
        export class EmployeesList implements OnInit{
          private employees: Employee[];
        
          constructor(private myService:MyService){}
        
          ngOnInit(): void{
             // it's better to do the subscription inside ngOnInit.
            this.myService.getAllEmployees().subscribe(
              employees => {
                 this.employees = employees; 
              }
            );  
          }
    
        }
    

    That's basically how you should do it. However, for better development and user experience, I advice using angular resolvers. Resolvers are basically methods that can be attached to a specific route and angular will call them before rendering the component. But that's considered as an advanced topic, I will not post any codes for that unless you asked me for.

    Please mark it as correct if the answer did help you. All the best!

    Edit After discussing below in the comments, I understood that you have different back-ends to communicate with depending on the current route, I would handle this case just like this:

        // inside the component 
        constructor(private router: Router) {}
        ngOnInit(){
                // You need to find 
                this.myService.getAllEmployees(this.router.url).subscribe(
                  employees => {
                     this.employees = employees; 
                  }
        
                );
          
        }
    
    // inside the service file:
    
        export class MyService{
            
                constructor(private myRequiredService: RequiredService) {}
            
                getAllEmployees(URL: string):Observable<Employee[]>{
                   // decide which back-end to connect with depending on the URL
                   switch(url){
                    case "example1":
                                    URL = "url1";
                             break;
                    case "example2":
                                    URL = "url2";
                             break;
                   }
                   // Connect to the resource using URL param
                   // return Observables of type Employee[]
                }
        }