Angularjs2 - 在应用程序启动之前预加载服务器配置[重复]

Posted

技术标签:

【中文标题】Angularjs2 - 在应用程序启动之前预加载服务器配置[重复]【英文标题】:Angularjs2 - preload server configuration before the application starts [duplicate] 【发布时间】:2016-12-26 07:22:46 【问题描述】:

我正在使用 Angular2 RC5。我希望能够在我的应用程序启动之前加载我的服务器 IP 地址和一些其他配置参数。如何在最新的 RC5 中做到这一点?

我看过其他文章,但没有帮助:

    How to preload a config file in angular2:这里提供的答案是特定于 webpack 的。我正在使用 systemjs。 https://medium.com/@hasan.hameed/reading-configuration-files-in-angular-2-9d18b7a6aa4#.m8lontnas:这是针对旧版本的 Angular2。一些使用的类已被弃用。

任何帮助将不胜感激。

编辑

我尝试在我的 app.module.ts 中使用 APP_INITIALIZER,如下所示:

    import  NgModule, provide, APP_INITIALIZER        from "@angular/core";
    import  ConfigService  from "./shared/services/config.service";
    @NgModule(
        declarations: [AppComponent],
        imports: [BrowserModule,
            routes,
            FormsModule,
            HttpModule],
        providers: [AuthService,
            Title,
            appRoutingProviders,
            ConfigService],
        bootstrap: [AppComponent
            , provide(APP_INITIALIZER,
                
                    useFactory: (config: ConfigService) => () => config.load(),
                    deps: [ConfigService], multi: true
                )]
    )
    export class AppModule  

这是我的 config.service.ts 文件:

    import  Config  from "../model/config";

    export class ConfigService 
        constructor() 
        

        load(): Promise<Config> 
            let config: Config = new Config("localhost", "5050");
            return Promise.resolve(config);
        
    

请注意,我最终将重写 load 以实际读取属性或某些此类文件以加载配置。

这是 config.ts 的样子:

export class Config 

    constructor(
        private machine: string,
        private port: string
    ) 
    

    private base_url: string = "http://" + this.machine +
    this.port + "/";

    public loginURL: string = this.base_url + "login";

我得到一个编译错误

public/app/app.module.ts(27,11): error TS2345: Argument of type ' declarations: (typeof AppComponent ...' is not assignable to parameter of type 'NgModuleMetadataType'.
  Types of property 'bootstrap' are incompatible.
    Type '(typeof AppComponent | Provider)[]' is not assignable to type '(Type | any[])[]'.
      Type 'typeof AppComponent | Provider' is not assignable to type 'Type | any[]'.
        Type 'Provider' is not assignable to type 'Type | any[]'.
          Type 'Provider' is not assignable to type 'any[]'.
            Property '[Symbol.iterator]' is missing in type 'Provider'.

编辑 2

我继续下一步。更新 ConfigService 以使用 http.get 读取 json 文件。现在我得到一个错误。以下是更新后的文件:

export class ConfigService 
    private config: Config;
        constructor(private http: Http) 
    

    load(): Promise<Config> 
            this.http.get("/blah/config.json")
                 .map(res => res.json())
                 .subscribe((env_data) => 
                     console.log(env_data);
                  );
        this.config = new Config("localhost", "5050");
        return Promise.resolve(this.config);
    

    getConfig(): Config 
        return this.config;
    

这里是 NgModule 类中的 providers 部分

    providers: [AuthService,
    Title,
    appRoutingProviders,
    ConfigService,
    
        provide: APP_INITIALIZER,
        useFactory: (config: ConfigService) => () => config.load(),
        deps: [ConfigService, Http],
        multi: true
    ],

请注意,在 RC6 中,我无法导入 HTTP_PROVIDERS,因为我收到的错误是这些不再在 http 模块中定义。这就是我尝试 Http 的原因。

在运行时,我收到以下错误

(index):27 Error: Error: Can't resolve all parameters for ConfigService: (?).(…)(anonymous function) @ (index):27
ZoneDelegate.invoke @ zone.js:332
Zone.run @ zone.js:225(anonymous function) @ zone.js:591
ZoneDelegate.invokeTask @ zone.js:365
Zone.runTask @ zone.js:265
drainMicroTaskQueue @ zone.js:497
ZoneTask.invoke @ zone.js:437

【问题讨论】:

【参考方案1】:

在你的根模块中提供这个

provide: APP_INITIALIZER, useValue: () => promise, multi: true]

其中() =&gt; promise 是一些调用,它返回一个解析为所需值的 Promise。

另见How to pass parameters rendered from backend to angular2 bootstrap method

您可以将服务作为依赖项传递,您可以在其中存储结果。

更新

export function loadConfig(config: ConfigService) => () => config.load()

@NgModule(
        declarations: [AppComponent],
        imports: [BrowserModule,
            routes,
            FormsModule,
            HttpModule],
        providers: [AuthService,
            Title,
            appRoutingProviders,
            ConfigService,
             provide: APP_INITIALIZER,
              useFactory: loadConfig,
              deps: [ConfigService], 
              multi: true 
        ],
        bootstrap: [AppComponent]
    )
    export class AppModule  

更新 2

Plunker example

【讨论】:

你好。我已经按照您在我的根目录NgModule 中的建议提供了ConfigService,但是当我在浏览器config.load() 中进行调试时,它总是返回未定义。 使用AOT时,useFactory不应该获取动态函数,而是导出函数。见***.com/a/41636880/499839 @Mika 感谢您的提示!当我发布答案时,AoT 并不是真正的事情。更新了我的答案。 问题是config.load()方法中的promise只有在初始化之后才会被解析。你知道如何管理这个吗? 所以你的意思是 return () => return startupService.load() ;是吗?

以上是关于Angularjs2 - 在应用程序启动之前预加载服务器配置[重复]的主要内容,如果未能解决你的问题,请参考以下文章

启动预加载,请稍后

Microsoft Edge WebView2 控件可以在显示之前预加载页面吗?

预加载音频文件/事件?

iis的预加载已启用要开吗?

是否可以在 webview 上显示之前预加载 html

SpriteKit:播放前将声音文件预加载到内存中?