在 APP_INITIALIZER 承诺解决之前构建 Angular (v5) 服务 [英] Angular (v5) service is getting constructed before APP_INITIALIZER promise resolves

查看:28
本文介绍了在 APP_INITIALIZER 承诺解决之前构建 Angular (v5) 服务的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我希望 Angular 在构建其他服务之前等待我的 loadConfig() 函数解析,但事实并非如此.

I'm expecting Angular to wait until my loadConfig() function resolves before constructing other services, but it is not.

app.module.ts

export function initializeConfig(config: AppConfig){
    return () => config.loadConfig();
}

@NgModule({
     declarations: [...]
     providers: [
          AppConfig,
         { provide: APP_INITIALIZER, useFactory: initializeConfig, deps: [AppConfig], multi: true }
     ] })
export class AppModule {

}

app.config.ts

@Injectable()
export class AppConfig {

    config: any;

    constructor(
        private injector: Injector
    ){
    }

    public loadConfig() {
        const http = this.injector.get(HttpClient);

        return new Promise((resolve, reject) => {
            http.get('http://mycoolapp.com/env')
                .map((res) => res )
                .catch((err) => {
                    console.log("ERROR getting config data", err );
                    resolve(true);
                    return Observable.throw(err || 'Server error while getting environment');
                })
                .subscribe( (configData) => {
                    console.log("configData: ", configData);
                    this.config = configData;
                    resolve(true);
                });
        });
    }
}

some-other-service.ts

@Injectable()
export class SomeOtherService {

    constructor(
        private appConfig: AppConfig
    ) {
         console.log("This is getting called before appConfig's loadConfig method is resolved!");
    }
 }

SomeOtherService 的构造函数在从服务器接收数据之前被调用.这是一个问题,因为 SomeOtherService 中的字段没有设置为正确的值.

The constructor of SomeOtherService is getting called before the data is received from the server. This is a problem because then the fields in SomeOtherService do not get set to their proper values.

如何确保 SomeOtherService 的构造函数仅在 loadConfig 的请求得到解决后才被调用?

How do I ensure SomeOtherService's constructor gets called only AFTER the loadConfig's request is resolved?

推荐答案

我还有一个类似的问题,对我来说解决了这个问题的是使用 Observable 方法和运算符来做所有事情.然后最后只需要使用 ObservabletoPromise 方法返回一个 Promise.这也更简单,因为您不需要自己创建承诺.

I had also a simmilar issue what solved the issue for me was to use Observable methods and operators to do everything. Then in the end just use the toPromise method of the Observable to return a Promise. This is also simpler because you don't need to create a promise yourself.

AppConfig 服务看起来像这样:

import { Injectable, Injector } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import { tap } from 'rxjs/operators/tap';

@Injectable()
export class AppConfig {

    config: any = null;

    constructor(
        private injector: Injector
    ){
    }

    public loadConfig() {
        const http = this.injector.get(HttpClient);

        return http.get('https://jsonplaceholder.typicode.com/posts/1').pipe(
          tap((returnedConfig) => this.config = returnedConfig)
        ).toPromise();
        //return from([1]).toPromise();
    }
}

我正在使用新的管道操作符在谷歌为 Angular 5 推荐的 rxjs 中. tap 操作符等效于旧的 do 操作符.

I'm using the new pipeable operators in rxjs which is recommended by Google for Angular 5. The tap operator is equivalent to the old do operator.

我还在 stackblitz.com 上创建了一个工作示例,因此您可以将其设置为正常工作.示例链接

I have also created a working sample on stackblitz.com so you can se it working. Sample link

这篇关于在 APP_INITIALIZER 承诺解决之前构建 Angular (v5) 服务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆