Angular2 APP_INITIALIZER nested http requests

2019-07-12 20:45发布

问题:

I've been trying to use the APP_INITIALIZER during the bootstrap process to load some configuration data (similar to How to pass parameters rendered from backend to angular2 bootstrap method, Angular2 APP_INITIALIZER not consistent, and others).

The problem I'm facing is that I need to make 2 requests, the first one to a local json file where a URL resides, then the request to that URL to get the actual configuration.

For some reason however the startup is not delayed until the promise resolves.

This is the load method that gets called via the APP_INITIALIZER

public load(): Promise<any> 
{
  console.log('bootstrap loading called');
  const promise = this.http.get('./src/config.json').map((res) => res.json()).toPromise();
  promise.then(config => {

    let url = config['URL'];
    console.log("loading external config from: ./src/" + url);

    this.http.get('./src/' + url).map(r => r.json()).subscribe(r => { this.config = r; console.dir(r);});
  });
  return promise;
}

And here is a complete plnkr demonstrating the problem (check the console output).

Obviously I'm missing an important understanding of the concept.

How can I get the app to wait for both requests to return before the component is loaded?

回答1:

1) Return promise

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

2) Keep order

public load(): Promise<any> {
  return this.http.get('./src/config.json')
        .map((res) => res.json())
        .switchMap(config => {
          return this.http.get('./src/' + config['URL']).map(r => r.json());
        }).toPromise().then((r) => {
          this.config = r;
        });
}

Plunker Example

or withour rxjs operator

public load(): Promise<any> {
  return new Promise(resolve => {
    const promise = this.http.get('./src/config.json').map((res) => res.json())
      .subscribe(config => {
        let url = config['URL'];
        this.http.get('./src/' + url).map(r => r.json())
          .subscribe(r => { 
            this.config = r;
            resolve();
          });
      });
  });
}

Plunker Example



回答2:

You are not returning any promise in the provided plunkr:

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

should actually be:

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

or

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