typescript - page - title service angular
Inicialización asÃncrona del servicio Angular 2. (2)
Tengo un servicio de Angular 2 que necesita realizar un trabajo asíncrono cuando está inicializado y no debería poder utilizarse antes de que se haya completado esta inicialización.
@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
}
}
En su estado actual, este servicio se inicializa y se devuelve inmediatamente a cualquier componente que lo use. Ese componente luego llama a getSomethingFromServer()
en su ngOnInit
, pero en ese momento Api.user no se inicializa y, por lo tanto, se envía una solicitud incorrecta.
Los ganchos del ciclo de vida ( OnInit
, OnActivate
, etc.) no funcionan con servicios, solo componentes y directivas, por lo que no puedo usarlos.
El almacenamiento de la llamada Promise from get()
requeriría todos los métodos diferentes que dependen del usuario para esperarla, lo que provocaría una gran cantidad de duplicación de código.
¿Cuál es la forma recomendada de hacer una inicialización asíncrona de servicios en Angular 2?
Después de trabajar un poco con la respuesta de Thierry, descubrí que solo funcionaría una vez, pero me puso en el camino correcto. En su lugar, tuve que almacenar la promesa del usuario y crear un nuevo observable que luego se hace flatMap
.
@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(...);
});
}
}
}
Esto asegura que la función flatMap
reciba al usuario cada vez que se le llame, en lugar de solo la primera vez, como en la respuesta de Thierry.
Podría aprovechar un observable para hacer eso con el operador flatMap
. Si el usuario no está allí, puede esperar y luego encadenar la solicitud de destino.
Aquí hay una muestra:
@Injectable()
export class Api {
private user;
private storage;
private userInitialized = new Subject();
constructor(private http: Http) {
this.storage = LocalStorage;
this.storage.get(''user'').then(json => {
if (json !== "") {
this.user = JSON.parse(json);
this.userInitialized.next(this.user);
}
});
}
// one of many methods
public getSomethingFromServer(): Observable<...> {
// make a http request that depends on this.user
if (this.user) {
return this.http.get(...).map(...);
} else {
return this.userInitialized.flatMap((user) => {
return this.http.get(...).map(...);
});
}
}
}