2

I've this scenario.

backend.json

{
"devServer": "http://server1/'",
"proServer" : "http://server2/'",
"use" :  "devServer"
}

global.service.ts

import {Injectable} from '@angular/core';
import {Http, HTTP_PROVIDERS, Response, RequestOptions, URLSearchParams} from '@angular/http';
@Injectable()
export class GlobalService {
constructor(private _http: Http){}
getBackendServer(){
    return this.server = this._http.get('./backend.json')
        .map((res:Response) => res.json())
}
}

And I've this other service: search.service.ts

import {Injectable} from '@angular/core';
import {Http, HTTP_PROVIDERS, Response, RequestOptions, URLSearchParams} from '@angular/http';
import {GlobalService} from '../services/global.service';
import 'rxjs/add/operator/map';
@Injectable()
export class SearchService {
server;
constructor( private _http: Http, private gs: GlobalService ) {
    this.server = gs.getBackendServer().subscribe(
        (data) => {
            this.server = data[data.use];
        },
        (err) => {
            console.log(err);  
        }
    );
}
DoGeneralSearch(params:Search){
    console.log(this.server);
    let options = this.buildOptions(params);
    return this._http.get(this.server + 'room/search', options)
     .map((res:Response) => res.json())
} 
}

What I want to do: Looks obvious: I want to keep the information regarding the URL of the backend server in a JSON file - And the global service should return the server so this can be used in any method of the search service.

The problem is: the DoGeneralSearch() method executes before the global service is capable to resolve the task to read the JSON file and return the result. So, I've a this.server = Subscriber {isUnsubscribed: false, syncErrorValue: null, syncErrorThrown: false, syncErrorThrowable: false, isStopped: false…} instead the result itself.

I need to find some how to prevent the method DoGeneralSearch be executed just after resolved the this.server variable.

Any suggestions ?

1 Answer 1

7

I think that you could preload such hints at the application startup. For this, you could leverage the APP_INITIALIZER service. The application will wait for the returned promise to be resolved before actually starting.

Here is a sample:

provide(APP_INITIALIZER, {
  useFactory: (service:GlobalService) => () => service.load(),
  deps:[GlobalService, HTTP_PROVIDERS], multi: true
})

The load method would like something like that:

load():Promise<Site> {
  var promise = this.http.get('config.json').map(res => res.json()).toPromise();
  promise.then(config => this.devServer = config.devServer);
  return promise;
}

Then you can directly use the devServer (synchronously)...

See this issue on github for more details:

Sign up to request clarification or add additional context in comments.

4 Comments

Excellent hint on APP_INITIALIZER! Finally, the 'how to pause the app before initialization' question from AngularJS days got a fair answer.
Hi, I have done this approach but when I debug the promise service.load() from the APP_INITIALIZER provider, It always return undefined. I have verified that the load method returns a value in the GlobalService but this module seems to be loaded at the end of the application loading process.
Also, using @nglibs\config in your project, that will provide you required config data from backend.json which got resolved during application initalization
In APP_INITIALIZER service i need to make two HTTP call from various services. Is there any way to initialize

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.