我应该在其构造函数中还是在 app.component 的 ngOnInit 方法中初始化 Angular 服务?

Posted

技术标签:

【中文标题】我应该在其构造函数中还是在 app.component 的 ngOnInit 方法中初始化 Angular 服务?【英文标题】:Should I initialise an Angular service in its constructor or in the ngOnInit method of the app.component? 【发布时间】:2020-10-02 02:58:16 【问题描述】:

我是 Angular 的新手。我有一项服务需要订阅另一个服务提供的主题。如果这是一个组件,我会在组件的 ngOnInit 方法中创建订阅。不过,服务不需要 NgOnInit。我创建了一个初始化方法来创建订阅,但我不确定从哪里最好地调用它。我已经看到它做了两种方式:

1) 在服务构造函数中调用initialise方法

2) 将服务注入到 app.component 中,并在 app.component 的 ngOnInit 方法中调用服务初始化方法,例如

方法一:

export class MyService

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

    initaliseSubs()
        //code to set up subscriptions
    


方法二


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();

  

这两种方法似乎都有效,但我欢迎就哪种方法更可取提出建议。提前致谢。

【问题讨论】:

【参考方案1】:

服务是您定义可观察对象的地方,例如getAllEmployees(),组件是您使用这些服务的地方(将服务注入构造函数)。

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

假设现在您有一个名为EmployeesList 的组件,它负责显示所有员工数据,首先,您需要将服务注入构造函数,然后您需要调用getAllEmployees 服务方法并订阅,以便获取数据。

    export class EmployeesListimplements OnInit
      private employees: Employee[];
    
      constructor(private myService:MyService)
    
      ngOnInit()
         // it's better to do the subscription inside ngOnInit.
        this.myService.getAllEmployees().subscribe(
          employees => 
             this.employees = employees; 
          

        );
  
      
    

基本上你应该这样做,但是为了更好的开发和更好的用户体验,我建议使用angular resolvers,解析器基本上是可以附加到特定路由的方法,并且角度会在渲染组件之前调用它们,在这些内部方法您需要订阅getAllEmployees 服务方法并获取组件内部的值,使用解析器的主要目标是避免渲染视图然后等待从资源中获取数据。 但这被认为是一个高级主题,除非您要求我,否则我不会发布任何代码。

如果答案对您有帮助,请将其标记为正确。 万事如意!

编辑 在下面的 cmets 中讨论后,我了解到您有不同的后端可以根据当前路由进行通信,我会这样处理这种情况:

    // 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[]
            
    

【讨论】:

"最好在 ngOnInit 内部进行订阅。" - 你能详细说明为什么这是“更好”的方式吗? 非常感谢您的快速答复。你的例子是我 90% 的应用程序是如何工作的。我只是有一个不寻常的案例。该应用程序根据用于访问它的路线与不同的后端进行对话(网站有自己的网址和自己的后端)。站点服务根据 url 设置站点。身份验证服务将登录请求传递给相关的后端,如果站点发生变化,前端应该要求用户重新登录。因此,auth 服务需要订阅站点服务中的站点主题。因此需要初始化一个服务中对另一个服务中的主题的订阅。 @GeorgeKitching 欢迎您,我理解服务方法的后端 url 总是在变化,我认为您应该将 URL 作为参数传递给服务,而不是在服务内部订阅。因为您可以知道从组件内部调用了哪个路由,这取决于您可以决定调用哪个后端。 @PhilippMeissner 请在此处查看此答案:***.com/a/35763811/10121188 @FurqanS.Mahmoud。谢谢你。那可能行得通。我会考虑一下的。是否有任何理由避免在服务中订阅?它似乎有效,但我热衷于避免不可预见的陷阱。

以上是关于我应该在其构造函数中还是在 app.component 的 ngOnInit 方法中初始化 Angular 服务?的主要内容,如果未能解决你的问题,请参考以下文章

我应该将变量放在类还是构造函数中? PHP

我应该使用构造函数注入还是 IoC.Resolve?

当我的服务在其构造函数中有可注入对象时,如何将服务注入我的测试?

在其派生类C++的构造函数中调用基类的构造函数[重复]

如何在其构造函数中获取使用依赖注入的类的实例

Python:float的子类可以在其构造函数中获取额外的参数吗?