0

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

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

这是我实现 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();

这确实编译但不起作用

最后一个是我最接近它的工作,但我知道这是一个糟糕的 observables 实现:

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

我在使用这种方法时遇到的另一个问题是,如果嵌套的 observable 什么都不返回,它就不起作用,所以我不得不做一个即兴的解决方案,但我想知道如果嵌套的 observable 什么都不返回,flatMap 或 mergeMap 是否不起作用

4

1 回答 1

3

为了将一个 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));
于 2017-11-25T01:53:07.237 回答