【问题标题】:How to run a service when the app starts in Angular 2当应用程序在 Angular 2 中启动时如何运行服务
【发布时间】:2016-05-13 12:14:15
【问题描述】:

我创建了一个服务SocketService,基本上它初始化套接字让应用程序监听端口。该服务还与一些组件交互。

// socket.service.ts

export class SocketService {
    constructor() {
        // Initializes the socket
    }
    ...
}

我知道 SocketService 的 constructor() 中的代码只有在组件使用 SocketService 时才开始运行。

通常 app.ts 中的代码如下所示:

// app.ts

import {SocketService} from './socket.service';
...
class App {
    constructor () {}
}
bootstrap(App, [SocketService]);

但是,我希望在应用启动时运行此服务。所以我做了一个技巧,在App的constructor()中添加private _socketService: SocketService。所以现在代码看起来像这样:

// app.ts(新)

import {SocketService} from './socket.service';
...
class App {
    constructor (private _socketService: SocketService) {}
}
bootstrap(App, [SocketService]);

现在可以了。问题有时是 SocketService 的 constructor() 中的代码运行,有时不是。那么我应该如何正确地做到这一点呢?谢谢

【问题讨论】:

标签: typescript angular


【解决方案1】:

Stuart 的回答指出了正确的方向,但在 APP_INITIALIZER 上查找信息并不容易。简短的版本是您可以在任何其他应用程序代码运行之前使用它来运行初始化代码。我搜索了一段时间,找到了herehere的解释,我会总结一下,以防它们从网络上消失。

APP_INITIALIZER 在 angular/core 中定义。你像这样将它包含在你的 app.module.ts 中。

import { APP_INITIALIZER } from '@angular/core';

APP_INITIALIZER 是一个引用 ApplicationInitStatus 服务的 OpaqueToken(或 Angular 4 以来的 InjectionToken)。 ApplicationInitStatus 是一个multi provider。它支持多个依赖项,您可以在提供程序列表中多次使用它。它是这样使用的。

@NgModule({
  providers: [
    DictionaryService,
    {
      provide: APP_INITIALIZER,
      useFactory: (ds: DictionaryService) => () => return ds.load(),
      deps: [DictionaryService],
      multi: true
    }]
})
export class AppModule { }

此提供程序声明告诉 ApplicationInitStatus 类运行 DictionaryService.load() 方法。 load() 返回一个承诺,ApplicationInitStatus 会阻止应用程序启动,直到承诺解决。 load() 函数是这样定义的。

load(): Promise<any> {
  return this.dataService.getDiscardReasons()
  .toPromise()
  .then(
    data => {
      this.dictionaries.set("DISCARD_REASONS",data);
    }
  )
}

设置为首先加载字典,应用程序的其他部分可以安全地依赖它。

编辑:请注意,无论 load() 方法花费多长时间,这都会增加您的应用程序的前期加载时间。如果你想避免这种情况,你可以在你的路线上使用resolver

【讨论】:

  • 谢谢你...非常有帮助
  • 这应该是公认的答案。当前仅将一行代码从构造函数移动到init 方法。虽然构造函数确实应该尽可能简单,但仅凭这种想法并不能使其成为正确的解决方案。使用APP_INITIALIZER 可以。
  • 我不认为选择的答案是错误的,因为它解决了 OP 的问题。 但是,由于我在某些图书馆的开发中遇到了类似的问题,我已经打开了another question这个答案非常适合。
  • 最好的方法
  • 我认为这个解决方案只有在 dataService 没有使用任何 Angular 服务时才有效。因为否则您会收到“无法实例化循环依赖!ApplicationRef”错误。 More Details
【解决方案2】:

SocketService 构造函数中的逻辑移到一个方法中,然后在主组件的构造函数或 ngOnInit 中调用它

SocketService

export class SocketService{
    init(){
        // Startup logic here
    }
}

应用程序

import {SocketService} from './socket.service';
...
class App {
    constructor (private _socketService: SocketService) {
        _socketService.init();
    }
}
bootstrap(App, [SocketService]);

【讨论】:

  • 我不明白 do stuff in the method 而不是构造函数背后的逻辑是什么,请您解释一下,在方法中执行逻辑有什么好处?
  • 更简洁的方法恕我直言
  • 构造函数应该尽可能简单(通常只有注入点),以防你需要添加额外的逻辑使用 ngOnInit 钩子。
  • 团队还没有想到的另一件事。我在 Angular 4 上工作的越多,我意识到 Aurelia 框架是多么出色。只需添加一个装饰器,它就拥有所有这些开箱即用的可能性。那些家伙知道他们在做什么。
  • @CodyBugstein 这取决于您的用例。如果它只是一劳永逸,那么只需调用异步方法。如果您需要等待结果,您可以从您的init() 方法返回一个Promise,然后根据需要进行链接。不管是什么情况,它可以完成,但可能会很困难,具体细节由你决定。如果您需要进一步的帮助,您可以随时发布问题,详细说明您的问题,社区很乐意为您提供帮助。
【解决方案3】:

另见APP_INITIALIZER,其描述为;

应用程序初始化时将执行的函数。

【讨论】:

    【解决方案4】:

    尝试创建服务构造函数,然后在组件的 ngOnInit() 中调用它。

    • 服务模块

     export class SocketService {
        constructor() { }
            getData() {
                //your code Logic
            }
    }
    • 组件

    export class AppComponent {
        public record;  
        constructor(private SocketService: DataService){ }
        ngOnInit() {        
            this.SocketService.getData()
            .subscribe((data:any[]) => {
                this.record = data;
            });   
      }  
    }       

    希望对您有所帮助。

    【讨论】:

    • @Hongbo 希望服务在应用启动时运行,而不是在使用该服务的特定组件中运行
    • 这个非常简单的答案对我有用。我喜欢简单的答案。谢谢。
    【解决方案5】:
    in config.teml.json
    {Domain:'your url'}
    
    in app.module.ts
    
    import * as mydata from '../assets/config.teml.json';
    const data:any=(mydata as any).default;
    let config: SocketIoConfig = { url: data.Domain, options: { } };
    

    【讨论】:

    • 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-02-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多