meorfi meorfi - 29 days ago 15
TypeScript Question

angular2 Observable: How to wait asynchronous result and return another asynchronous method

I have to resolve a problem with asynchronous calls.
Scenario:

makeReservation
method returns
Observable<SaveResponse>
. When
makeReservation
method is called by a caller should do

1) invoke
send3DRequest
and subscribe to it and wait for
success
Event.

2) in
success
event get necessary details and return another asynchronous method:
return this.reservationHttpService.save(X)


In my actual implementation I get an error:
Return statement is required for non-void return type
.

private makeReservation(reservationDto: ReservationDTO): Observable<SaveResponse>{
this.reservationHttpService.send3DRequest(reservationDto.threeDQueryDetails)
.subscribe(
successResponse => {
if(successResponse.enrolled === 'Y'){
reservationDto.transRef = successResponse.transactionRef;
reservationDto.acsUrl = successResponse.acsUrl;
reservationDto.paReq = successResponse.paReq;

return this.reservationHttpService.save(reservationDto);
}
else {
reservationDto.transRef = successResponse.transactionRef;

return this.reservationHttpService.save(reservationDto);
}
},
error => { throw new Error(error); });
}


--

Then, I tried to make this change (the problem is described in code):

private makeReservation(reservationDto: ReservationDTO): Observable<SaveResponse>{

let saveResponse = new Observable<SaveResponse>(); //added change

this.reservationHttpService.send3DRequest(reservationDto.threeDQueryDetails)
.subscribe(
successResponse => {
if(successResponse.enrolled === 'Y'){
reservationDto.transRef = successResponse.transactionRef;
reservationDto.acsUrl = successResponse.acsUrl;
reservationDto.paReq = successResponse.paReq;

let result = this.reservationHttpService.save(reservationDto);
//HOW TO INSERT the result in saveResponse and notify about change ?
}
else {
reservationDto.transRef = successResponse.transactionRef;
let result = this.reservationHttpService.save(reservationDto);
//HOW TO INSERT the result in saveResponse and notify about change ?
}
},
error => { throw new Error(error); });

return saveResponse; //added change
}


Any idea would are welcome :)
Thanks.

Answer

If you take a look to your method definition :

private makeReservation(reservationDto: ReservationDTO): Observable<SaveResponse>

You expect makeReservation method to return an Observable of type SaveResponse. But you do not return anything here.

You just start to subscribe on reservationHttpService.send3DRequest.

You should rather have :

private makeReservation(reservationDto: ReservationDTO): Observable<SaveResponse>{
  return this.reservationHttpService.send3DRequest(reservationDto.threeDQueryDetails)

(notice the return).


So now, if we start from your second example (which is probably the best idea), I'd do something like :

private makeReservation(reservationDto: ReservationDTO): Observable<SaveResponse>{
  return this
    .reservationHttpService
    .send3DRequest(reservationDto.threeDQueryDetails)
    .switchMap(response => {
        let result;

        if(successResponse.enrolled === 'Y') {
          reservationDto.transRef = successResponse.transactionRef;
          reservationDto.acsUrl = successResponse.acsUrl;
          reservationDto.paReq = successResponse.paReq;

          result = this.reservationHttpService.save(reservationDto);
        }

        else {
          reservationDto.transRef = successResponse.transactionRef;
          result = this.reservationHttpService.save(reservationDto);
        }

        return Observable.of(result);
      }
    )
    .catch(err => {
      // handle your error here
      return Observable.of({});
    })
}

and just don't forget to subscribe on makeReservation when you call it :

this.makeReservation(your_argument).subscribe();

Comments