Angular4 APP_INITIALIZER不会延迟初始化

Dyn*_*Web 26 configuration initialization angular-cli angular

打字稿:2.2.0 Angular:4.0

我试图通过使用确保ConfigService在应用程序启动之前初始化对象APP_INITIALIZER.我发现了很多如何做到这一点的例子,但是他们似乎没有延迟应用程序的初始化.以下是我尝试实施的一些示例.

https://github.com/angular/angular/issues/9047 https://gist.github.com/fernandohu/122e88c3bcd210bbe41c608c36306db9 Angular2 APP_INITIALIZER不一致

这是我的NgModule

export function init(config: ConfigService) {
  return () => {
    config.load();
  };
}


@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    FormsModule,
    HttpModule,
    AppRoutingModule
  ],
  providers: [
    {
      'provide': APP_INITIALIZER,
      'useFactory': init,
      'deps': [ConfigService],
      'multi': true
    },
    ConfigService
  ],
  bootstrap: [AppComponent]
})
export class AppModule {
}
Run Code Online (Sandbox Code Playgroud)

这是ConfigService班级

@Injectable()
export class ConfigService {
  private config: ApplicationConfiguration;

  get apiRoot() {
    return this.getProperty('apiRoot'); // <--- THIS GETS CALLED FIRST
  }

  constructor(private http: Http) {
  }

  load(): Promise<any> {
      console.log('get user called');
      const promise = this.http.get('./../../assets/config.json').map((res) => res.json()).toPromise();
      promise.then(config => {
        this.config = config;     // <--- THIS RESOLVES AFTER
        console.log(this.config);
      });
    return promise;
  }

  private getProperty(property: string): any {
    //noinspection TsLint
    if (!this.config) {
      throw new Error(`Attempted to access configuration property before configuration data was loaded, please double check that 'APP_INITIALIZER is properly implemented.`);
    }

    if (!this.config[property]) {
      throw new Error(`Required property ${property} was not defined within the configuration object. Please double check the 
      assets/config.json file`);
    }

    return this.config[property];
  }
}
Run Code Online (Sandbox Code Playgroud)

并测试一切我已经注入ConfigServiceAppComponent这一点.

import { Component } from '@angular/core';
import {ConfigService} from './services/config.service';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent {
  title = 'app works!';
  fullImagePath = '/src/image/avatar.jpeg';


  constructor(private config: ConfigService) {
    config.apiRoot;
  }
}
Run Code Online (Sandbox Code Playgroud)

yur*_*zui 21

看起来你忘了从工厂返回价值:

export function init(config: ConfigService) {
  return () => {
    return config.load(); // add return
  };
}
Run Code Online (Sandbox Code Playgroud)

或者相同的代码可以写一点:

export function init(config: ConfigService) {
   return () => config.load();
}
Run Code Online (Sandbox Code Playgroud)

  • 这有一个微妙的错误.虽然在通过config.load()确定配置加载之前应用程序不会引导,但是在config.load()完成之前很久,您的ConfigService将作为服务提供注入其他服务.是的,你编写的注入ConfigService的所有其他服务都会注入一个不完整/尚未加载的对象.因此,您需要非常小心应用程序的其余部分如何使用ConfigService,因为您正在处理尚未完成构建的对象.不要依赖于注射器/工厂订购的幸运. (6认同)
  • 对于阅读此内容的其他人来说,这也是最新的(截至目前)https://juristr.com/blog/2018/01/ng-app-runtime-config/#runtime-configuration (3认同)
  • @JoelDavey在我的[功能请求](https://github.com/angular/angular/issues/23279)上投票,以便ng团队为我们提供解决方案.我请求异步提供商,但我们会看到他们做了什么. (3认同)