Rxjs 组合流
Rxjs combining streams
好的,基本上我想要实现的是一个依赖于另一个可观察对象的可观察对象,例如联合查询。
为了详细说明,我有两个表,一个是活动,另一个是这些活动的最终日期,所以我要做的是首先获取活动,然后搜索这些活动的最终日期,最好是能够将两个流组合成 return 一个数组,其中包含单个新对象中的活动和最终日期。
我尝试过不同的实现方式,但都没有成功。
下面是我如何实现我的 service.ts(表的两种服务是相同的):
private actividadesSubject = new BehaviorSubject([]);
private actividades: ActividadPlaneacion[];
// <------------------------ GET ------------------------>
getActividades(): Observable<ActividadPlaneacion[]>{
return this.actividadesSubject.asObservable();
}
loadActividades(){
var sub = this.http.get(this.url+'select/actividadPlaneacion')
.map(this.extractData)
.catch(this.handleError);
sub.subscribe(
data => this.actividades = data,
err => console.log(err),
() => this.refresh()
);
}
private refresh() {
this.actividadesSubject.next(this.actividades);
}
以及我尝试实现此目的的各种方法(在 component.ts 上):
MergeMap
this.actividadService.getActividades().mergeMap( actividad =>
this.actividadFechasFinalService.getActividadByIDYear(actividad.ID, actividad.Anio).subscribe( actividades => this.arregloActividadesFlatMap = actividades ));
(这不编译)
平面地图:
this.actividadService.getActividades().flatMap( actividad => {
this.actividadFechasFinalService.getActividadByIDYear(actividad[0].ID, actividad[0].Anio).subscribe( actividades => this.arregloActividadesFechasFinales = actividades );
return Observable.of(actividad)});
this.actividadService.loadActividades();
这可以编译但不起作用
最后一个是我能用的最接近的,但我知道这是一个糟糕的可观察对象实现:
this.actividadService.getActividades().flatMap((actividades: any[]) => {
if(actividades.length > 0){
return Observable.forkJoin(
actividades.map((actividad: any) => {
return this.actividadFechasFinalService.getActividadByIDYear(actividad.ID, actividad.Anio)
.map((res: any) => {
let actividadPlaneacion;
console.log(res);
console.log('j = '+this.j);
this.j++;
if(res.length > 0){
res.map( (object) => {
console.log(this.i);
this.i++;
console.log(object);
console.log('object');
//console.log(res[0].FechaFinal);
//let object: any = res;
actividadPlaneacion = new ActividadPlaneacionMasFechasFinales(actividad.ID, actividad.Descripcion, actividad.Nombre, actividad.FechaInicio, actividad.Responsable,
actividad.Practica, actividad.Departamento, actividad.Evidencia, actividad.Producto, object.Actividad, object.FechaFinal, object.Completado, actividad.Anio);
let exists = this.arreglo.find(fecha => fecha.FechaFinal == actividadPlaneacion.FechaFinal);
console.log(exists);
if(exists == undefined)
this.arreglo.push(actividadPlaneacion);
this.arreglo = this.arreglo.sort(function(a, b){
if ( a.FechaFinal < b.FechaFinal )
return -1;
if ( a.FechaFinal > b.FechaFinal )
return 1;
return 0;
});
});
} else{
let existsActividad = this.arreglo.find(fecha => fecha.FechaFinal == actividad.FechaFinal);
console.log(existsActividad);
if(existsActividad == undefined){
actividadPlaneacion = new ActividadPlaneacionMasFechasFinales(actividad.ID, actividad.Descripcion, actividad.Nombre, actividad.FechaInicio, actividad.Responsable,
actividad.Practica, actividad.Departamento, actividad.Evidencia, actividad.Producto, null, null, null, actividad.Anio);
} else {
const index: number = this.arreglo.indexOf(existsActividad);
if (index !== -1) {
this.arreglo.splice(index, 1);
}
} //capitulo
let exists = this.arreglo.find(fecha => fecha.FechaFinal == actividadPlaneacion.FechaFinal);
console.log(exists);
if(exists == undefined)
this.arreglo.push(actividadPlaneacion);
}
return actividadPlaneacion;
});
})
);
}
console.log('FINALLL');
if(actividades.length == 0)
this.getActividades();
return actividades;
}).subscribe(
actividades => this.arregloActividadesFlatMap = actividades
);
this.actividadService.loadActividades();
我用这种方法遇到的另一个问题是,如果嵌套的 obervable return 什么都没有,它就不起作用,所以我不得不做一个临时的解决方案,但我想知道 flatMap 或 mergeMap 是否没有'如果嵌套的 observables return 什么都没有
则无法工作
为了将一次 http 调用的结果提供给第二次调用,您可以使用 switchMap、mergeMap 或 concatMap。
forkJoin 比 运行 独立调用更适合你有多个调用的地方,你只想合并所有调用的结果 return.
选择的选项取决于您希望如何处理多个并发调用,例如。如果用户多次点击加载按钮并排队多个请求会发生什么?总结:
- switchMap - 将丢弃所有未完成的请求并且仅 return
最后一个请求的结果被触发
- mergeMap - 将 return 所有并发请求按顺序排列
他们 return 来自服务器(可能与中的顺序不匹配
他们被要求
- concatMap - 将 return 所有结果按它们原来的顺序排列
要求
一个使用 switchMap 的简单例子是:
this.http.get('https://jsonplaceholder.typicode.com/posts')
.switchMap((result) => {
// add your logic here to get data from first request to
// feed to second request
const firstId = result.response[0].id
if (firstId) {
return this.http.get('https://jsonplaceholder.typicode.com/comments/' + firstId);
} else {
// if you don't have what you need return your own observable
return Observable.of('No results');
}
})
.subscribe(result => console.log(result));
好的,基本上我想要实现的是一个依赖于另一个可观察对象的可观察对象,例如联合查询。 为了详细说明,我有两个表,一个是活动,另一个是这些活动的最终日期,所以我要做的是首先获取活动,然后搜索这些活动的最终日期,最好是能够将两个流组合成 return 一个数组,其中包含单个新对象中的活动和最终日期。
我尝试过不同的实现方式,但都没有成功。
下面是我如何实现我的 service.ts(表的两种服务是相同的):
private actividadesSubject = new BehaviorSubject([]);
private actividades: ActividadPlaneacion[];
// <------------------------ GET ------------------------>
getActividades(): Observable<ActividadPlaneacion[]>{
return this.actividadesSubject.asObservable();
}
loadActividades(){
var sub = this.http.get(this.url+'select/actividadPlaneacion')
.map(this.extractData)
.catch(this.handleError);
sub.subscribe(
data => this.actividades = data,
err => console.log(err),
() => this.refresh()
);
}
private refresh() {
this.actividadesSubject.next(this.actividades);
}
以及我尝试实现此目的的各种方法(在 component.ts 上): MergeMap
this.actividadService.getActividades().mergeMap( actividad =>
this.actividadFechasFinalService.getActividadByIDYear(actividad.ID, actividad.Anio).subscribe( actividades => this.arregloActividadesFlatMap = actividades ));
(这不编译)
平面地图:
this.actividadService.getActividades().flatMap( actividad => {
this.actividadFechasFinalService.getActividadByIDYear(actividad[0].ID, actividad[0].Anio).subscribe( actividades => this.arregloActividadesFechasFinales = actividades );
return Observable.of(actividad)});
this.actividadService.loadActividades();
这可以编译但不起作用
最后一个是我能用的最接近的,但我知道这是一个糟糕的可观察对象实现:
this.actividadService.getActividades().flatMap((actividades: any[]) => {
if(actividades.length > 0){
return Observable.forkJoin(
actividades.map((actividad: any) => {
return this.actividadFechasFinalService.getActividadByIDYear(actividad.ID, actividad.Anio)
.map((res: any) => {
let actividadPlaneacion;
console.log(res);
console.log('j = '+this.j);
this.j++;
if(res.length > 0){
res.map( (object) => {
console.log(this.i);
this.i++;
console.log(object);
console.log('object');
//console.log(res[0].FechaFinal);
//let object: any = res;
actividadPlaneacion = new ActividadPlaneacionMasFechasFinales(actividad.ID, actividad.Descripcion, actividad.Nombre, actividad.FechaInicio, actividad.Responsable,
actividad.Practica, actividad.Departamento, actividad.Evidencia, actividad.Producto, object.Actividad, object.FechaFinal, object.Completado, actividad.Anio);
let exists = this.arreglo.find(fecha => fecha.FechaFinal == actividadPlaneacion.FechaFinal);
console.log(exists);
if(exists == undefined)
this.arreglo.push(actividadPlaneacion);
this.arreglo = this.arreglo.sort(function(a, b){
if ( a.FechaFinal < b.FechaFinal )
return -1;
if ( a.FechaFinal > b.FechaFinal )
return 1;
return 0;
});
});
} else{
let existsActividad = this.arreglo.find(fecha => fecha.FechaFinal == actividad.FechaFinal);
console.log(existsActividad);
if(existsActividad == undefined){
actividadPlaneacion = new ActividadPlaneacionMasFechasFinales(actividad.ID, actividad.Descripcion, actividad.Nombre, actividad.FechaInicio, actividad.Responsable,
actividad.Practica, actividad.Departamento, actividad.Evidencia, actividad.Producto, null, null, null, actividad.Anio);
} else {
const index: number = this.arreglo.indexOf(existsActividad);
if (index !== -1) {
this.arreglo.splice(index, 1);
}
} //capitulo
let exists = this.arreglo.find(fecha => fecha.FechaFinal == actividadPlaneacion.FechaFinal);
console.log(exists);
if(exists == undefined)
this.arreglo.push(actividadPlaneacion);
}
return actividadPlaneacion;
});
})
);
}
console.log('FINALLL');
if(actividades.length == 0)
this.getActividades();
return actividades;
}).subscribe(
actividades => this.arregloActividadesFlatMap = actividades
);
this.actividadService.loadActividades();
我用这种方法遇到的另一个问题是,如果嵌套的 obervable return 什么都没有,它就不起作用,所以我不得不做一个临时的解决方案,但我想知道 flatMap 或 mergeMap 是否没有'如果嵌套的 observables return 什么都没有
则无法工作为了将一次 http 调用的结果提供给第二次调用,您可以使用 switchMap、mergeMap 或 concatMap。
forkJoin 比 运行 独立调用更适合你有多个调用的地方,你只想合并所有调用的结果 return.
选择的选项取决于您希望如何处理多个并发调用,例如。如果用户多次点击加载按钮并排队多个请求会发生什么?总结:
- switchMap - 将丢弃所有未完成的请求并且仅 return 最后一个请求的结果被触发
- mergeMap - 将 return 所有并发请求按顺序排列 他们 return 来自服务器(可能与中的顺序不匹配 他们被要求
- concatMap - 将 return 所有结果按它们原来的顺序排列 要求
一个使用 switchMap 的简单例子是:
this.http.get('https://jsonplaceholder.typicode.com/posts')
.switchMap((result) => {
// add your logic here to get data from first request to
// feed to second request
const firstId = result.response[0].id
if (firstId) {
return this.http.get('https://jsonplaceholder.typicode.com/comments/' + firstId);
} else {
// if you don't have what you need return your own observable
return Observable.of('No results');
}
})
.subscribe(result => console.log(result));