2

I am trying to implement nested api calls in ionic3

submitLoginForm() {
    var username = this.formData.value.username;
    var password = this.formData.value.password;
    var bodyjson;
    var userId;

    this.ApidataService.logincheck(username,password).subscribe(data => {
        this.logindetail = data;
        bodyjson = JSON.parse(this.logindetail._body);
        userId =  bodyjson.user.id;
        if( userId != undefined){
            this.ApidataService.userdata(userId).subscribe(data => {
                this.userInfo = data;
            });
        }
        console.log(userId);
    });
    console.log(this.userInfo);
}

Now when I call this function the nested api returns undefined for the first call and then from the second call onwards it returns proper values however when I try to log the argument that is being sent to the api I notice that the correct value is passed each time. I believe that this is due to some synchronization issues but am unable to figure out the issue and the solution for the same.

Sampath
  • 63,341
  • 64
  • 307
  • 441
OshoParth
  • 1,492
  • 2
  • 20
  • 44
  • instead of `( userId != undefined)` just check like `( userId )` – Rahul Singh Aug 17 '17 at 07:02
  • 1
    You can find the angular version of the duplicate here: https://stackoverflow.com/questions/43055706/how-do-i-return-the-response-from-an-observable-http-async-call-in-angular2. What you are doing is trying to access the response of an async operation synchronously. Javascript doesn't work like that. The link covers the fundemantals of async behaviour of js. If you want to chain your observables, you can check: https://stackoverflow.com/questions/36712659/angular-2-two-backend-service-calls-on-success-of-first-service/36712707#36712707 – eko Aug 17 '17 at 07:30

1 Answers1

0

You can use flatMap here.It seems you don't need to retrieve results of both requests hence this should work for you.

 import { Observable } from "rxjs/Observable";
 import 'rxjs/add/observable/flatMap';

Then:

 this.ApidataService.logincheck(username,password).flatMap(
  (data) => {
        this.logindetail = data;
        bodyjson = JSON.parse(this.logindetail._body);
        userId =  bodyjson.user.id;
        if( userId != undefined){
          return this.ApidataService.userdata(userId);
        }else{
          return Observable.empty();
        }
    }).map((res: Response) => res ? res.json() : {})
    .subscribe(data => {
           this.userInfo = data ? data : {};
    });

You can read more about flatMap here

Sampath
  • 63,341
  • 64
  • 307
  • 441
  • 1
    **Always** using `forkJoin` is a strong claim in my opinion. There are several other ways to handle this situation. E.g `flatMap/mergeMap` – eko Aug 17 '17 at 07:31
  • 1
    Corrected.Thanks for the info @echonax – Sampath Aug 17 '17 at 07:32
  • No problem. But then again your answer is wrong because the `forkJoin` makes the requests in parallel. In OP's situation 1 async calls request depends on the others' response. So.. – eko Aug 17 '17 at 07:33
  • 1
    Oh..I didn't see that.I'll see the link which you have a shared.Thanks again :) @echonax – Sampath Aug 17 '17 at 07:36
  • Can you please see is this correct now? @echonax – Sampath Aug 17 '17 at 08:14
  • Ehm, no because the return type of the `flatMap` needs to be an `Observable`, you are returning a `Subscription`. You need to subscribe to it at the end. And if `userId == undefined`, this code will blow up. – eko Aug 17 '17 at 08:17
  • Any correction please on above post? @echonax – Sampath Aug 17 '17 at 08:18
  • I did but the question is a duplicate and duplicate questions shouldn't be answered :-) – eko Aug 17 '17 at 08:27
  • 1
    Thanks a lot.I have learned a lot.Yeah..But I posted this (Wrong one) before the tagged `Duplicate`.So no issues I think.Thanks again :) @echonax – Sampath Aug 17 '17 at 08:29
  • This does not seem to work it says error [16:34:53] typescript: src/pages/login/login.ts, line: 63 Property 'flatMap' does not exist on type 'Observable'. L63: this.ApidataService.logincheck(username,password).flatMap( L64: (data) => { [16:34:53] typescript: src/pages/login/login.ts, line: 71 Property 'empty' does not exist on type 'typeof Observable'. L70: }else{ L71: return Observable.empty(); – OshoParth Aug 18 '17 at 11:06
  • You need to import this `import 'rxjs/add/observable/flatMap';`. – Sampath Aug 18 '17 at 11:25