0

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.

1 Answers1

1

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[]
            }
    }
chri3g91
  • 1,196
  • 14
  • 16
Furqan S. Mahmoud
  • 1,417
  • 2
  • 13
  • 26
  • "it's better to do the subscription inside ngOnInit." - Can you elaborate on why that is the "better" way? – Philipp Meissner Jun 12 '20 at 10:45
  • Many thanks for a speedy answer. Your example is how 90% of my app works. I just have an unusual case. The app talks to different backends depending on the route used to access it (sites have their own urls and own backends). A sites service sets the site based on the url. An auth service passes a login request to the relevant backend, If the site changes, the front end should require the user to log in again. As such, the auth service needs to subscribe to a site subject in the sites service. Hence the need to initialise a subscription in a service to a subject in another service. – George Kitching Jun 12 '20 at 11:25
  • @GeorgeKitching You welcome, I understood that the back-end url of the service method is always changing, I think you should pass the URL as a parameter to the service instead of subscribing inside the service. because you can know which route is called from inside the component, depending on that you can decide which back-end to call. – Furqan S. Mahmoud Jun 12 '20 at 13:27
  • @PhilippMeissner please take a look at this answer here: https://stackoverflow.com/a/35763811/10121188 – Furqan S. Mahmoud Jun 12 '20 at 13:28
  • @FurqanS.Mahmoud. Thank you. That might work. I'll give it some thought. Is there any reason for avoiding subscribing within a service? It seems to work, but I am keen to avoid unforseen pitfalls. – George Kitching Jun 12 '20 at 15:10
  • @GeorgeKitching it will work, but the code will not be consistent, I will edit the answer to give you a close look. – Furqan S. Mahmoud Jun 13 '20 at 07:10
  • @FurqanS.Mahmoud. Yes, I think you've convinced me. I might have been overthinking it. Doing it the way you suggest actually simplifies something else I need to do too. Thanks again for your help. – George Kitching Jun 13 '20 at 10:00