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));