1

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.

2
  • use promise to handle Async request Commented Jun 18, 2019 at 9:35
  • Use rxjs operators, like switchmap. Check the token response if 200 just return the new observable if is 401 or 404 return empty observable like of. Commented Jun 18, 2019 at 9:41

3 Answers 3

2

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
Sign up to request clarification or add additional context in comments.

4 Comments

I have changed my code to your suggestion. But i'm now getting the following error: ERROR TypeError: Cannot read property 'pipe' of undefined looks like pipe is not imported? I cannot find the correct solution.
@WouterDoornbos pipe can be applied to observables. The signature of your function returns a token, so I assumed you made an HTTP call. Could you post the code of your checkToken function ?
No, not the full code. In the event that the token is expired there will be a api call to get a new token and save it in localstorage. This part is a bit too long to post.
@WouterDoornbos well that's the whole point if you want me to adapt my answer ... Anyway, you HAVE TO return an observable in checkToken in order for my code to work.
0

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[]>())
  );
}

Comments

0

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[]>()));
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.