在Angular中导入模块后,如何从模块中自动运行服务?

时间:2019-08-05 15:30:16

标签: angular typescript

我想知道如何在导入模块时不进行任何手动服务注入和运行就如何从模块中运行服务,就像RouterModule一样。

@NgModule({
  imports: [

    BroserModule,
    MyModuleWithServicesThatShouldAutoRun,

  ]
})
export class AppModule { }

2 个答案:

答案 0 :(得分:1)

  

免责声明:这是基于another answer的,因为没有更简单的方法可以执行OP所需的操作,因此未被接受为正确答案。

您可以使用APP_INITIALIZER注入令牌在运行任何其他应用程序代码之前运行初始化代码。

APP_INITIALIZER@angular/core中定义,您可以这样包含它:

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

APP_INITIALIZEROpaqueToken,它引用了 multi provider ApplicationInitStatus服务。它支持多种依赖关系,您可以在提供商列表中多次使用它,例如:

@NgModule({
  providers: [
    MyService,
    {
      provide: APP_INITIALIZER,
      useFactory: (service: MyService) => function() { return service.init(); },
      deps: [MyService],
      multi: true
    }]
})
export class AppModule { }

此提供程序声明正在告诉ApplicationInitStatus类运行MyService.init()方法。 init()返回Promise,而ApplicationInitStatus阻止应用启动,直到Promise解析为止。

export class MyService {

  // omitted other methods for brevity

  init(): Promise<any> {

    // start some observers, do the stuff you need

    // you can even request something via http
    return this.httpClient
      .get('https://someurl.com/example')
      .toPromise()
  }

}

这样,init中的所有内容都会运行并阻止应用程序加载,直到Promise解析为止。

请注意,无论init()方法花费多长时间,这都会增加您应用的前期加载时间。要在打开路线之前加载内容,请改用resolver

来源:

答案 1 :(得分:0)

RouterModule的用途是使用forRoot()forChild()(有时称为forFeature())方法,这是在模块加载时进行配置的惯例。有关here的详细说明,请参见。

如果您查看RouterModule's source code,您会发现forRoot()forChild()像下面这样配置模块:

providers: [
        ROUTER_PROVIDERS,
        provideRoutes(routes),
        {
          provide: ROUTER_FORROOT_GUARD,
          useFactory: provideForRootGuard,
          deps: [[Router, new Optional(), new SkipSelf()]]
        },
       // many more, omitted
]

在该位置,您还可以按照其他答案中的说明添加APP_INITIALIZER,这将有效地使您的导入模块看起来像这样:

@NgModule({
  imports: [

    BroserModule,
    MyModuleWithServicesThatShouldAutoRun.forRoot( /* some config, maybe */),

  ]
})
export class AppModule { }