Angular 2 - Services consuming others services before call a method
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 ?
Solution 1:
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:
- https://github.com/angular/angular/issues/9047