在其他提供商中使用APP_INITIALIZER

时间:2019-07-08 13:35:46

标签: angular typescript

我正在使用APP_INITIALIZER挂钩从本地json文件加载一些应用程序配置。加载配置后,我想在另一个提供程序中使用它(为生成的swagger-codegen服务设置BASE_PATH)。

我收到此错误:Uncaught TypeError: Cannot read property 'api' of undefined

我尝试访问AppInitService.settings.api的值是AppInitService上的静态属性。我怀疑这是问题所在,但据我了解,APP_INITIALIZER挂钩应保证在继续之前先等待...

如何等待将值加载到APP_INITIALIZER中并准备好在其他提供者useValue中重用?

app.module.ts

    export function initializeApp(appConfig: AppInitService) {
        return (): Promise<any> => appConfig.init()
    }

    @NgModule({
        declarations: [...],
        imports: [...],
        providers: [
            AppInitService,
            {
                provide: APP_INITIALIZER,
                useFactory: initializeApp,
                deps: [AppInitService],
                multi: true,
            },
            {
                provide: BASE_PATH,
                useValue: AppInitService.settings.api,
            },
        ],

app.config.service.ts

    @Injectable()
    export class AppInitService {
        static settings: IAppConfig
        private conf: IAppConfig

        constructor(private http: HttpClient) {}

        public getConf() {
            return this.conf
        }

        init() {
            const jsonFile = `assets/config/config.json`
            return this.http
                .get(jsonFile)
                .pipe(
                    tap((returnedConfig: IAppConfig) => {
                        console.log('returnedConfig', returnedConfig)
                        AppInitService.settings = returnedConfig
                        this.conf = returnedConfig
                    })
                )
                .toPromise()
        }
    }

1 个答案:

答案 0 :(得分:1)

您可以使用工厂提供程序。

{
    provide: BASE_PATH,
    useFactory: (service: AppInitService) => service.conf, // doesn't need to be static
    deps: [AppInitService]
}

Angular只会在提供程序解析后第一次第一次调用工厂函数,但是您只是假设将在以后解析 。它可能暂时可以使用,但是以后可能会损坏甚至根本无法使用。

相反,使用可观察值作为可注入值。

@Injectable()
public class AppInitService {
    public conf: ReplaySubject<any> = new ReplaySubject(1);

    init() {
       const jsonFile = `assets/config/config.json`
       return this.http
            .get(jsonFile)
            .pipe(
                tap((returnedConfig: IAppConfig) => this.conf.next(returnedConfig))
            ).toPromise()
    }
}