I have a two functions as below:
refreshAccessToken() {
let rt = this.injector.get(LocalStorageService);
var tokenData = rt.getAuthorizationData();
var refreshToken = tokenData.refresh_token;
var refreshToken = localStorage.getItem('userRefreshToken');
if (refreshToken !== null) {
var data = "grant_type=refresh_token&refresh_token=" + refreshToken;
var basicAuth = btoa("crmClient1:crmSuperSecret");
var headerData = {
"Content-Type": "application/x-www-form-urlencoded",
"Authorization": "Basic " + basicAuth,
"No-Auth": "True",
'Access-Control-Allow-Origin': '*'
};
var reqHeader = new HttpHeaders(headerData);
this.http.post(this.tokenUrl, data, {
headers: reqHeader
})
.subscribe((response: any) => {
this.localStorageService.setAuthorizationData(response);
console.log("I need to be called first");
});
} else {
return null;
}
}
getNewAccessToken(): Observable < string > {
this.refreshAccessToken();
console.log("I need to be called as a second value");
var varTokenData = this.localStorageService.getAuthorizationData();
var newAccessToken = varTokenData.access_token;
this.newat = newAccessToken;
return of(this.newat);
}
I am calling refreshAccessToken()
function inside getNewAccessToken()
function. Here, the code is doing fine except that the codes:
console.log("I need to be called as a second value");
var varTokenData = this.localStorageService.getAuthorizationData();
var newAccessToken = varTokenData.access_token;
this.newat = newAccessToken;
return of(this.newat);
are executed before the complete execution of function refreshAccessToken()
. How do I make other codes wait for execution until the refreshAccessToken()
function is completely executed in angular 6?
The error I am getting is as below:
The section of AuthInterceptor from where I a calling getNewAccessToken() function is as below:
//generating new token from refresh_token
handle401Error(req: HttpRequest<any>, next: HttpHandler) {
console.log("Error 401 called");
if (!this.isRefreshingToken) {
this.isRefreshingToken = true;
// Reset here so that the following requests wait until the token
// comes back from the refreshToken call.
this.tokenSubject.next(null);
return this.loginService.getNewAccessToken()
.pipe(
switchMap((newToken: string) => {
if (newToken) {
this.tokenSubject.next(newToken);
//this.isRefreshingToken=false;
return next.handle(this.addToken(req, newToken));
}
// If we don't get a new token, we are in trouble so logout.
//this.isRefreshingToken=false;
return this.logout();
}),
catchError(error => {
// If there is an exception calling 'refreshToken', bad news so logout.
//this.isRefreshingToken=false;
//console.log(error);
return this.logout();
})
//)
),
finalize(()=>{
this.isRefreshingToken=false;
});
} else {
return this.tokenSubject
.pipe(
filter(token => token !=null)
),
take(1),
switchMap((token: string )=> {
return next.handle(this.addToken(req,token));
});
}
}
The Typescript wait is one of the features for to wait for the process which is executed by the end-users; it can be applicable for both compile-time and run-time execution the asynchronous process is wrapped over the promises also the user will set the time interval for all the formats like seconds, milliseconds and ...
Wait for function to finish using async/await keywords As you already know from the Promise explanation above, you need to chain the call to the function that returns a Promise using then/catch functions. The await keyword allows you to wait until the Promise object is resolved or rejected: await first(); second();
The second function checkDuplicate() we have subscribed to that function getData() . and we have third function called proceed() in which we call the checkDuplicate() function and once the checkDuplicate() function is completed, we are calling alert("finished").
Basically, Async/Await works on top of Promise and allows you to write async code in a synchronous manner. It simplifies the code and makes the flow and logic more understandable. Note that because it no longer uses then and catch chaining anymore, you can handle errors by running try/catch.
You can return
an Observable
from your refreshAccessToken
method:
import { of } from 'rxjs';
import { tap } from 'rxjs/operators';
refreshAccessToken(): Observable<any> {
...
if (refreshToken !== null) {
...
return this.http.post(this.tokenUrl, data, {
headers: reqHeader
})
.pipe(tap(response => this.localStorageService.setAuthorizationData(response)));
} else {
return of(null);
}
}
And then subscribe to it from your getNewAccessToken
method like this:
getNewAccessToken(): Observable<string> {
this.refreshAccessToken()
.subscribe(response => {
...
});
}
Alternatively:
You could use async
/await
which were introduced in ES2017. Since they work only with functions dealing with promise
s and not Observable
s, you will have to change your functions a bit to return a promise
instead of Observable
.
Here's how:
import { of } from 'rxjs';
import { tap } from 'rxjs/operators';
refreshAccessToken() {
...
if (refreshToken !== null) {
...
return this.http.post(this.tokenUrl, data, {
headers: reqHeader
})
.pipe(tap(response => this.localStorageService.setAuthorizationData(response)))
.toPromise();
} else {
return of(null).toPromise();
}
}
And then declare getNewAccessToken
as async
and await
refreshAccessToken
:
async getNewAccessToken() {
await this.refreshAccessToken();
...
}
import { forkJoin } from "rxjs";
async ngOnInit() {
await this.getDataFromMultipleApis().then(data=>{
console.log(data);
});
}
getDataFromMultipleApis(){
return new Promise((res, rej) => {
forkJoin(
this.Service.api1(),
this.Service.api2()
).subscribe(docs => {
res(docs);
});
});
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With