web-dev-qa-db-fra.com

Configuration de chargement angulaire2 depuis le backend au démarrage

Dans mon application Angular2, j'essaie de charger des configurations depuis le backend au démarrage avec HTTP afin de pouvoir utiliser les données extraites pour créer des services angulaires.

Chaque fois que j'essaie de lire la réponse HTTP enregistrée dans ma configuration, j'obtiens toujours TypeError: Je ne peux pas lire la propriété 'url' de undefined error.

Il semble que la requête HTTP ne se termine que lorsque la méthode d'amorçage complète est terminée, alors que mon code tente d'extraire la réponse Observable avant qu'elle ne soit récupérée.

Comment puis-je résoudre ce problème pour extraire la configuration du serveur et l'utiliser pour créer des services angulaires au démarrage? (Je veux créer des services au sein de fournisseurs avec des données extraites)

Veuillez commenter s'il existe un meilleur moyen d'extraire la configuration du serveur au démarrage.

Mon main.ts ressemble à ceci:

bootstrap(AppComponent, 
    [APP_ROUTER_PROVIDERS, HTTP_PROVIDERS, ConfigurationService, Config])
    .catch(err => console.error(err)
);

configuration.service.ts

@Injectable()
export class ConfigurationService {

    constructor(private http: Http) {
    }

    load() {
        return this.http.get('config/getConfig').map(response => response.json());
    }

}

config.ts

@Injectable()
export class Config {

    public config;

    constructor(public configurationService: ConfigurationService) {
        configurationService.load().subscribe(
            config => this.config = config,
            error => console.error('Error: ' + error)
        );
    }

    get(key: any) {
        return this.config[key];
    }
}

app.component.ts

@Component({
    selector: 'app',
    templateUrl: 'app/app.component.html',
    styleUrls: ['app/app.component.css'],
    directives: [ROUTER_DIRECTIVES],
    providers: [MyService]
})
export class AppComponent {

    constructor(public myService: MyService) {
    }

}

my.service.ts

@Injectable()
export class MyService{

    private url;

    constructor(public config: Config) {
        this.url = config.get('url');
    }
}
14
Gamerz Sydney

Vous pouvez utiliser le service APP_INITIALIZER pour recharger la configuration avant le démarrage de l'application:

bootstrap(AppComponent, [
  {
     provide: APP_INITIALIZER,
     useFactory: (config:Config) => {
       return config.load();
     },
     dependency: [ Config ]
   }
]);

Pour cela, vous devez adapter un peu votre classe ConfigService:

@Injectable()
export class ConfigService {
  constructor(private http:Http) {}

  load() { // <------
    return new Promise((resolve) => {
      this.http.get(...).map(res=>res.json())
        .subscribe(config => {
          this.config = config;
          resolve();
        });
  }
}

Vous pourrez ensuite accéder directement aux propriétés de l'objet de configuration dans votre application.

12
Thierry Templier

Lors de l'utilisation de la compilation AoT, une erreur est générée car la fabrique est une fonction anonyme. Ce que vous devez faire ensuite, c'est exporter une fonction pour l'usine

export function ConfigLoader(configService: ConfigService) {
    return () => configService.load();
}

et la configuration de l'application ressemble à ceci:

@NgModule({
    declarations: [
        AppComponent
    ],
    imports: [
        HttpModule,
        BrowserModule
    ],
    providers: [
        ConfigService,
        {
            provide: APP_INITIALIZER,
            useFactory: ConfigLoader,
            deps: [ConfigService]
        }],
    bootstrap: [ AppComponent ]
})
export class AppModule {
}

référence https://github.com/angular/angular/issues/10789

9
Dainius Lukša

C'est un meilleur moyen d'écrire la fonction de chargement

public load() {
    let promise =this.http.get(url).map(res => res.json()).toPromise();
    promise.then(config =>  this.validation = config);
    return promise;
};
0
Jens Alenius