angular - ¿Cómo puedo combinar múltiples acciones con observable?
Estoy trabajando en un proyecto de Angular 4 y soy nuevo con Observable.
Mi objetivo es ejecutar una función después del resultado de tres solicitudes HTTP y enriquecer mis modelos con los resultados de las solicitudes HTTP.
Resolví mi problema con observable de la siguiente manera, pero creo que esta no es la forma correcta:
function loadData(callback: Function): void {
this.httpRequestUno().subscribe(next => {
this.httpRequestDue().subscribe(next => {
this.httpRequestTre().subscribe(next => {
callback();
}, error => {
console.log(error);
});
}, error => {
console.error(error);
});
}, error => {
console.error(error);
});
}
function httpRequestUno():Observable<any>{
let self = this;
return new Observable<any>((observer) => {
// my http request and...
self.attributo1 = httpResult;
observer.next(1);
});
}
function httpRequestDue():Observable<any>{
let self = this;
return new Observable<any>((observer) => {
// my http request and...
self.attributo2 = httpResult;
observer.next(2);
});
}
function httpRequestTre():Observable<any>{
let self = this;
return new Observable<any>((observer) => {
// my http request and...
self.attributo3 = httpResult;
observer.next(3);
});
}
¿Permite RxJS combinar múltiples acciones como en el siguiente pseudo-código?
function loadData(callback: Function): void {
this.httpRequestUno().combine(this.httpRequestDue).combine(this.httpRequestTre).subscribe(result => {
callback();
});
}
¿Hay una manera de pasar todos los resultados en un solo parámetro como el siguiente pseudocódigo?
this.httpRequestUno().combine(this.httpRequestDue).combine(this.httpRequestTre).subscribe(result => {
let httpRequestUnoResult = result[0];
let httpRequestDueResult = result[1];
let httpRequestTreResult = result[2];
callback();
});
[EDITAR]
He probado la solución de Oscar. El problema es que los callbacks de suscripción no se ejecutan, pero si añado un observer.completed() en una función, el "callback completado" se ejecuta, pero no puedo acceder a los datos.
Reproduje mi caso allí https://jsfiddle.net/2n6b0ug3/
Muchas gracias
Respuesta #1
Sí, con el operador forkJoin:
const subscription = forkJoin(
this.httpRequestUno(),
this.httpRequestDue(),
this.httpRequestTre()
).subscribe(value => {
// value is an array with the results:
[result-of-request-uno, results-of-rquest-due, result-of-request-tre]
}, error => {
);
De hecho, forkJoin también puede recibir un arreglo de observables, si quieres hacer que el número de solicitudes sea dinámico, y el observable resultante se completará cuando todos los demás observables se completen. Por supuesto, si uno de los observables lanza un error, obtendrás un error (el primero). En este caso, el resultado de los otros observables será ignorado.
Más información: https://www.learnrxjs.io/operators/combination/forkjoin.html
Es, aproximadamente, el equivalente de Promise.all
EDITAR
Hice un fork de tu jsfiddle para arreglar tu ejemplo: https://jsfiddle.net/hmv20xjh/1/. El problema en tu código es que tus observables nunca se completan, y forkJoin devuelve el último valor de un observable, y solo lo hace cuando se completan. Entonces, en tu código, el observable que forkJoin devuelve sigue esperando para siempre y nunca produce un valor.
En el mío, sin embargo, los observables sí completan. forkJoin es un buen operador para esperar a los observables que representan una solicitud HTTP, ya que solo producen un resultado y luego completan. Si necesitas combinar observables que producen múltiples resultados, sin esperar a que completen, necesitas usar operadores más complicados como flatMap o mergeMap
