I have an Angular 2 service that needs to do async work when it is initalized, and should not be usable before this initialization has been completed.
@Injectable()
export class Api {
private user;
private storage;
constructor(private http: Http) {
this.storage = LocalStorage;
this.storage.get('user').then(json => {
if (json !== "") {
this.user = JSON.parse(json);
}
});
}
// one of many methods
public getSomethingFromServer() {
// make a http request that depends on this.user
}
}
As it currently stands, this service is initialized, and returned immediately to any component that uses it. That component then calls getSomethingFromServer()
in its ngOnInit
, but at that point Api.user is not initialized, and therefore the wrong request is sent.
The lifecycle hooks (OnInit
, OnActivate
, etc) does not work with services, only components and directives, so I cannot use those.
Storing the Promise from get()
call would require all the different methods that depend on user to wait for it, causing a lot of code duplication.
What is the recommended way to do async initialization of services in Angular 2?
After working with Thierry's answer for a bit, I discovered that it would only work once, but it did set me on the right path. I had to instead store the promise of the user, and create a new observable which is then flatMap
-ed.
@Injectable()
export class Api {
private userPromise: Promise<User>;
constructor(private http: Http) {
this.userPromise = LocalStorage.get('user').then(json => {
if (json !== "") {
return JSON.parse(json);
}
return null;
});
}
public getSomethingFromServer() {
return Observable.fromPromise(this.userPromise).flatMap((user) => {
return this.http.get(...).map(...);
});
}
}
}
This ensures that the flatMap
function gets the user every time it is called, instead of just the first time, as in Thierry's answer.