2017-06-23 52 views
0

我有一個使用Angular 4的小引導問題。 我有一個配置文件(json),當我的應用程序啓動時從服務器加載(另請參閱here)。這工作到目前爲止。在APP_INITIALIZE後初始化其他提供程序

現在我有一個dependency需要配置值傳遞給一個forRoot方法。實施看起來是這樣的:

static forRoot(config: AppInsightsConfig): ModuleWithProviders { 
    return { 
     ngModule: ApplicationInsightsModule, 
     providers: [ 
      { provide: AppInsightsConfig, useValue: config } 
     ] 
    }; 
} 

我的想法是導入模塊,而不forRoot(),但CONFIGS(從服務器)後,通過提供AppInsightsConfig已經加載。

@NgModule({ 
    bootstrap: sharedConfig.bootstrap, 
    declarations: [...sharedConfig.declarations], 
    imports: [ 
     BrowserModule, 
     FormsModule, 
     HttpModule, 
     ApplicationInsightsModule, 
     ...sharedConfig.imports   
    ], 
    providers: [ 
     { provide: 'ORIGIN_URL', useValue: location.origin }, 
     { provide: 
      APP_INITIALIZER, 
      useFactory: (configService: ConfigService) =>() => configService.load(), 
      deps: [ConfigService], multi: true 
     }, 
     { provide: 
      AppInsightsConfig, 
      useFactory: (configService: ConfigService) => { 
       // outputs undefined, expected it to have the config 
       console.log(configService.config); 
       return { instrumentationKey: 'key from config' } 
      }, 
      // My idea was, if I add APP_INITIALIZER as dependency, 
      // the config would have been loaded, but this isn't the case. 
      deps: [APP_INITIALIZER, ConfigService] 
     }, 
     AppInsightsService 
    ] 
}) 

我如何提供AppInsightsConfig或AFTER我CONFIGS另一個服務已裝?

+0

您是使用路由還是在您自己的模塊上實現'forRoot'? –

+0

@Maximus否,forRoot打算從該第三方模塊的模塊中調用。 [見這個源文件](https://github.com/MarkPieszak/angular-application-insights/blob/master/index.ts) – martinoss

+1

你不能那樣做。從我對上面的代碼的理解中,你不需要。沒有'configService'的代碼,但是你可以在'AppInsightsConfig'中鏈接一個承諾並且修補返回的對象。 AppInsightsConfig最初不會有instrumentationKey,但在app init之後會有。 'deps:[APP_INITIALIZER,'會搞砸DI,但無濟於事。 – estus

回答

2

最後,我想出了以下解決方案:

  • 我合併了angular-application-insights包的來源(是不是我的初衷),以我的代碼基礎,能夠改變的東西,使得它很難對我來說做我想做的引導。我也反對cyclic dependencies。感謝MarkPieszak分享您的圖書館。

這是我的應用程序模塊看起來像現在:

import { Resolve, Router } from '@angular/router'; 
import { NgModule, APP_INITIALIZER } from '@angular/core'; 
import { BrowserModule } from '@angular/platform-browser'; 
import { FormsModule } from '@angular/forms'; 
import { HttpModule } from '@angular/http'; 

import { sharedConfig } from './app.module.shared'; 

import { SiteControlModule } from './site-control/site-control.module'; 
import { SiteControlComponent } from './site-control/site-control.component'; 
import { AuthModule } from './auth/auth.module'; 

import { ConfigService } from './core/config/config.service'; 

import { ApplicationInsightsModule } from './application-insights/application-insights.module'; 
import { ApplicationInsightsService } from './application-insights/application-insights.service'; 

import { CoreModule } from './core/core.module'; 

let initializeConfig = (aiService: ApplicationInsightsService, configService: ConfigService) =>() => { 
    let loadConfigPromise = configService.load(); 

    loadConfigPromise.then(() => { 
     aiService.config = configService.config.applicationInsights; 
     aiService.init(); 
    }); 

    return loadConfigPromise; 
}; 


@NgModule({ 
    bootstrap: sharedConfig.bootstrap, 
    declarations: [...sharedConfig.declarations], 
    imports: [ 
     BrowserModule, 
     FormsModule, 
     HttpModule, 
     AuthModule, 
     ...sharedConfig.imports, 
     CoreModule.forRoot(), 
     ApplicationInsightsModule.forRoot(), 
     SiteControlModule 
    ], 
    providers: [ 
     { provide: 'ORIGIN_URL', useValue: location.origin }, 
     { provide: 
      APP_INITIALIZER, 
      useFactory: initializeConfig, 
      deps: [ ApplicationInsightsService, ConfigService ], 
      multi: true 
     }  
    ] 
}) 
export class AppModule {  
} 

config.service.ts

import { Injectable } from '@angular/core'; 
import { Headers, RequestOptions, Http, Response} from '@angular/http'; 
import { Observable } from 'rxjs/Observable'; 
import 'rxjs/add/operator/toPromise'; 

import { Config } from './models/config.model'; 

@Injectable() 
export class ConfigService { 

    config : Config; 

    constructor(private http: Http) { 
     console.log('constructing config service'); 
    } 

    public load(): Promise<void> { 
     let headers = new Headers({ 'Content-Type': 'application/json' }); 
     let url = 'environment.json'; 

     let promise = this.http.get(url, { headers }) 
      .toPromise() 
      .then(configs => { 
       console.log('environment loaded'); 
       this.config = configs.json() as Config; 
      }) 
      .catch(err => { 
       console.log(err); 
      }); 

     return promise; 
    } 

} 

的應用insights.service.ts的改變的一部分

import { Injectable, Optional, Injector } from '@angular/core'; 
import { Router, NavigationStart, NavigationEnd } from '@angular/router'; 
import { AppInsights } from 'applicationinsights-js'; 
import 'rxjs/add/operator/filter'; 
import IAppInsights = Microsoft.ApplicationInsights.IAppInsights; 

import { ApplicationInsightsConfig } from '../core/config/models/application-insights.model'; 

@Injectable() 
export class ApplicationInsightsService implements IAppInsights { 

    context: Microsoft.ApplicationInsights.ITelemetryContext; 
    queue: Array<() => void>; 
    config: Microsoft.ApplicationInsights.IConfig; 

    constructor(@Optional() _config: ApplicationInsightsConfig, private injector: Injector) { 
     this.config = _config; 
    } 

    private get router(): Router { 
     return this.injector.get(Router); 
    } 

    ... 

application-insights.module.ts

import { NgModule, ModuleWithProviders, Optional, SkipSelf } from '@angular/core'; 
import { CommonModule } from '@angular/common'; 

import { ApplicationInsightsService} from './application-insights.service'; 

export * from './application-insights.service'; 

@NgModule({ 
    imports: [ CommonModule ], 
    declarations: [], 
    exports: [], 
    providers: [] 
}) 

export class ApplicationInsightsModule { 

    constructor(@Optional() @SkipSelf() parentModule: ApplicationInsightsModule) { 
     if (parentModule) { 
      throw new Error(
       'ApplicationInsightsModule is already loaded. Import it in the AppModule only'); 
     } 
    } 

    static forRoot(): ModuleWithProviders { 
     return { 
      ngModule: ApplicationInsightsModule, 
      providers: [ ApplicationInsightsService ] 
     }; 
    }  
} 
相關問題