Rxjs组合流

时间:2017-11-24 19:48:09

标签: angular rxjs behaviorsubject

基本上我想要实现的是一个可观察的,它依赖于另一个可观察的,如联合查询。 为了详细说明,我有两个表,一个是活动,另一个是这些活动的最后日期,所以我想要做的是先获取活动,然后搜索这些活动的最终日期,最好能够组合两个流,以便在一个新对象中返回一个包含活动和最终日期的数组。

我尝试了不同的实现而没有任何运气。

这是我如何实现我的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 ));

(这不会编译)

FlatMap:

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没有返回任何内容,它就不起作用,所以我不得不做一个即兴的解决方案但是我想知道flatMap或mergeMap是不是没有如果嵌套的observable没有返回任何内容

1 个答案:

答案 0 :(得分:2)

为了将一个http调用的结果提供给第二个调用,您可以使用switchMap,mergeMap或concatMap。

forkJoin比你可以独立运行的多个调用更适合你只需要在所有调用返回后组合所有调用的结果。

选择的选项取决于您希望如何处理多个并发呼叫,例如。如果用户多次单击加载按钮并将多个请求排队,会发生什么?总结:

  • switchMap - 将删除所有未完成的请求并仅返回 最后一次请求的结果
  • mergeMap - 将返回订单中的所有并发请求 他们从服务器返回(可能与订单中的顺序不匹配) 他们被要求
  • concatMap - 将按照它们的顺序返回所有结果 请求的

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