Tanwer
Tanwer

Reputation: 1583

Wait for multiple HTTP calls to end before doing something

I want to make two HTTP calls.

Below is my TypeScript Code

   CheckLogIn() {
    this.http.get<boolean>(this.baseUrl + 'api/LogIn/CheckLogIn/' + this.StaffCode).subscribe(result => {
      setTimeout(() => {
        if (result == true) {
          this.GetUserName();
          sessionStorage.setItem("UserID", this.StaffCode);
          this.router.navigate(['/log-tracker']);
        }
      }, 5000)
    }, error => console.log(error));
  }

 GetUserName() {
    this.http.get(this.baseUrl + 'api/Common/GetUserName/' + sessionStorage.getItem("UserID"), { responseType: 'text' }).subscribe(result => {
      console.log(result);
      sessionStorage.setItem("UserName", result);
    }, error => console.log(error));
  }

Here Inside CheckLogin() I am calling an endpoint and within response of this call I am invoking another one (GetUserName) and then redirecting to another page.

But checkLogin Does not wait for GetUserName to finish and redirect to page before second call finishes its work , hence session username is always null .

I tried using SetTimeout Function but it does not work here , is there any other way to put a delay before redirection , or any way to make first call wait until second call finishes its work ?

Upvotes: 0

Views: 3293

Answers (2)

UncleDave
UncleDave

Reputation: 7188

You're not waiting for GetUserName within CheckLogin you're just calling it and ignoring the result. You could try returning the observable from GetUserName - and there's also a good opportunity here to use other RXJS operators.

import 'rxjs/add/operator/filter';
import 'rxjs/add/operator/mergeMap';
import 'rxjs/add/operator/do';

CheckLogIn() {
  this.http.get<boolean>(this.baseUrl + 'api/LogIn/CheckLogIn/' + this.StaffCode)
    .filter(result => result)
    .do(() => sessionStorage.setItem("UserID", this.StaffCode))
    .mergeMap(() => this.GetUserName())
    .subscribe( // This does not execute until the observable from GetUserName is complete
       result => this.router.navigate(['/log-tracker']),
       error => console.log(error)
    );
}

GetUserName() { // I now return an observable
  return this.http.get(this.baseUrl + 'api/Common/GetUserName/' + sessionStorage.getItem("UserID"), { responseType: 'text' })
    .do(result => sessionStorage.setItem("UserName", result));
}

Now we do the following:

  1. Call CheckLogin
  2. If result is true, continue
  3. Set UserID in session storage
  4. Call GetUserName and replace our observable with it
  5. When the observable returned by GetUserName completes we can navigate

There's no need to replace RXJS with promises, it has a lot of power when you're doing asynchronous requests - it especially shines in cases such as this when you have multiple calls to do in a certain order, and conditions that have to be met.

Upvotes: 2

anud33p
anud33p

Reputation: 318

You can use Promise

CheckLogIn() {
  try {
    return new Promise((resolve, reject) => {
      this.http.get<boolean>(this.baseUrl + 'api/LogIn/CheckLogIn/' + this.StaffCode).subscribe(result => {
        setTimeout(() => {
          if (result == true) {
            this.GetUserName();
            sessionStorage.setItem("UserID", this.StaffCode);
            this.router.navigate(['/log-tracker']);
          }
        }, 5000)
      }, error => console.log(error));
      resolve();
    })
  } catch (error) {
    console.log(error);
  }
}

Call your Checklogin function Like this

this.CheckLogIn().then(()=>{
      this. GetUserName();
    });

Upvotes: 1

Related Questions