Angular async call inside an observable

I have a function to make expire date control for an Item. In this function i create an observable that checks if the item is new or not. If it´s new it works as expected but when a try to get some complementary data to define if its expiring date is when it does not work well.

If the call is made for a single Item it works fine but when i try to fill a table with several item it return undefined.

I think it is a matter of the async call. The subscriber is not waiting for the inner httprequest to finish before making a new call for the next item on the table.

1- Function that meke the call to get the expire date and set the proper status.

 /* ValueGetter para mostrar en la tabla si la droga está vencida o vigente */
      ctlVigencia(params){
        let message: string;   
        this.ds.ctlVencimientoDroga(params.data._id, params.data.informacion.fecha.vencimientoCertificado, null)
        .subscribe(res=> {
          console.log(res);

          if(res.fAsignada == null){
            message= 'No deterninado'
          } else {
            let now = moment(new Date());
            if (res.fAsignada > now ) {
              message= 'Vigente'
            } else {
              message= ('Vencida')
            }
          }
        })
        return message
      };

2) Function that returns the value of the expiration date.

  /*Control vencimiento droga */
    ctlVencimientoDroga(idSelected: string, vencimientoCertificado: Date, modeForm?: string){
      let retesteos: Retesteo[];
      const resObs= Observable.create((observer:Observer<{[key: string]: any}>) =>{
        if (modeForm == 'nuevo'){
          observer.next({fAsignada: vencimientoCertificado})
          observer.complete();
        } else{
          this.rs.dataRetesteo.subscribe(res=>{ 
            retesteos= res;
            if (retesteos && retesteos.length == 0) {
              if(vencimientoCertificado != null) {
                observer.next({fAsignada: vencimientoCertificado});
              } else {
                observer.next(null);
              }
            }
            /* From here and down is where is the problem */
            if (retesteos && retesteos.length > 0){
              let fechaUltimoRetesteoAprobado: Date;
              retesteos.forEach(element => {
                if (element.estado.estado == estadoAprobacion.Aprobado && (fechaUltimoRetesteoAprobado == null || element.fVencimiento > fechaUltimoRetesteoAprobado )){
                  fechaUltimoRetesteoAprobado= element.fVencimiento
                }
              });
              observer.next({fAsignada: fechaUltimoRetesteoAprobado});
            }
            observer.complete(); 
          });
          this.rs.getById(idSelected);
        }
      })
      return resObs;
  }
}

I appreciate your help.

Upvotes: 0

Views: 390

Answers (2)

Castro Roy
Castro Roy

Reputation: 7803

You are assigning the value to message inside an asynchronous operation, but returning message synchronously. Try modifying ctlVigencia to return an Observable and use map on the response of ctlVencimientoDroga.

ctlVigencia(params): Observable<string> {
  return this.ds.ctlVencimientoDroga(params.data._id, params.data.informacion.fecha.vencimientoCertificado, null)
  .pipe(map(res=> {
    console.log(res);

    if(res.fAsignada == null){
      message= 'No deterninado'
    } else {
      let now = moment(new Date());
      if (res.fAsignada > now ) {
        message= 'Vigente'
      } else {
        message= ('Vencida')
      }
    }
    
    return message;
  }))
};

Please, not that I've changed subscribe for pipe and used map. Now, when invoking ctlVigencia you should subscribe

ctlVigencia(params).subscribe(message => console.log(message));

Upvotes: 0

bryan60
bryan60

Reputation: 29305

I would rewrite pretty much all of this to make use of operators...

  ctlVigencia(params){  
     // use map operator, return observable
    return this.ds.ctlVencimientoDroga(params.data._id, params.data.informacion.fecha.vencimientoCertificado, null)
    .pipe(map(res=> {
      console.log(res);
      if(res.fAsignada == null){
        return 'No deterninado'
      } else {
        let now = moment(new Date());
        if (res.fAsignada > now ) {
          return 'Vigente'
        } else {
          return 'Vencida'
        }
      }
    }));
  };


ctlVencimientoDroga(idSelected: string, vencimientoCertificado: Date, modeForm?: string){
  let retesteos: Retesteo[];
  if (modeForm == 'nuevo') {
    // return mock observable
    return of({fAsignada: vencimientoCertificado});
  }
  // return this observable and use map operator
  return this.rs.dataRetesteo.pipe(
      map(res=> { 
        retesteos = res;
        if (retesteos && retesteos.length == 0) {
          if(vencimientoCertificado != null) {
            return {fAsignada: vencimientoCertificado};
          } else {
            return null;
          }
        } else {
          let fechaUltimoRetesteoAprobado: Date;
          retesteos.forEach(element => {
            if (element.estado.estado == estadoAprobacion.Aprobado && (fechaUltimoRetesteoAprobado == null || element.fVencimiento > fechaUltimoRetesteoAprobado )){
              fechaUltimoRetesteoAprobado = element.fVencimiento
            }
          });
          this.rs.getById(idSelected); // unclear why or when this should happen
          return {fAsignada: fechaUltimoRetesteoAprobado};
        }
      })
  );
}

then whoever wants the value from ctlVigencia needs to subscribe to it.

Upvotes: 1

Related Questions