Wouter Doornbos
Wouter Doornbos

Reputation: 124

Issue with multiple observables in Typescript

I have a service named API and the first thing the service has to do is checking if the API token is valid, when the token is valid continue executing the called function. The issue here is that requesting a new token and the API call are being called at the same time.

I have tried changing the checkToken function to await and changing the final API call to async, that does not work because the function is an Observable.

Function checkToken

/*
This function has to run FIRST before the api call (below) is beigin executed.
The issue now is both functions are running at the same time, when the token is expired the call will fail. 
*/

checkToken(): Observable<any> {
    //this function will check the API token and either request a new token or do nothing.

    // Check if session is valid based on timestamp
    if (Number(currentTimestamp) + 5000 >= Number(userSession)) {
         // Session is valid, do nothing.
         return;
    } else {
         // Get new token and save in storage
         return;
    }
}

Example of a API call (i have multiple types of calls in my service)

getValuations(): Observable<Valuation[]> {
     this.checkToken(); // This function has to run (and complete)  first before continue.

     //The issue now is that the function below is executing at the same time as 
     checkToken()  

     return this.http.get<Valuation[]>();
}

Here i'm consuming the data.

 this.apiService.getValuations(this.Taxid).subscribe(res => {

 });

I expect the checkToken function to run first and continue with the getValuations function. But obviously they are executing at the same time, what will result in executing the API call with a invalid token.

Upvotes: 1

Views: 345

Answers (3)

user2216584
user2216584

Reputation: 5602

You should update your code like this:

checkToken(): Observable<any> {

        //this function will check the API token and either request a new token or do nothing.

        // Check if session is valid based on timestamp
        if (Number(currentTimestamp) + 5000 >= Number(userSession)) {
            // Session is valid, do nothing.
            //and let the observable pipe line handle it
            return of(true);
        } else {
            // Get new token and save in storage
            //session is not valid then first get the token and save ithe new token in the storage
            //adjust this code to have API which gets the new token
            return this.apiMethodWhichGetsTheNewToken()
                            .pipe(
                                map(newToken => {
                                    //save the token in the storage....

                                    return true;
                                })
                            )
        }
    }

And now use checkToken() method which returns an observable like this:

getValuations(): Observable<Valuation[]> { 
     return this.checkToken()
       .pipe(switchMap(token => this.http.get<Valuation[]>()));
}

Upvotes: 0

emkay
emkay

Reputation: 807

You simply need to pipe the response of new token creation or checking. Something on these lines.

//this is returning an observable, simply pipe its response.
checkToken(): Observable<any> {
//this function will check the API token and either request a new token or do nothing.
}



getValuations(): Observable<Valuation[]> {
  //this is going to call checkToken() first, when that is complete
  // this.http.get() request will be called.
  return this.checkToken().pipe(
    mergeMap(_ =>  this.http.get<Valuation[]>())
  );
}

Upvotes: 0

user4676340
user4676340

Reputation:

Use the switchMap operator :

getValuations(): Observable<Valuation[]> { 
     return this.checkToken()
       .pipe(switchMap(token => this.http.get<Valuation[]>()));
}

This will

  • Check the token
  • once the response is received, make the second request
  • return the result of the second request

Upvotes: 2

Related Questions