代码之家  ›  专栏  ›  技术社区  ›  Darío Villalta

Rxjs组合流

  •  0
  • Darío Villalta  · 技术社区  · 8 年前

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

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

    以下是我如何实现我的服务。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);
    }
    

    我试图通过各种方式(在组件上)实现这一点: 合并地图

    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什么都不返回,那么它就不起作用,所以我不得不做一个临时解决方案,但我想知道如果嵌套的obervable什么都不返回,flatMap或mergeMap是否起作用

    1 回复  |  直到 8 年前
        1
  •  3
  •   glendaviesnz    8 年前

    为了将一个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));
    
    推荐文章