Reputation: 2609
I am trying to access the token in the constructor, like below in utils.service.ts file:
storage.get('token').then((val) => {
this.token = val;
console.log("token: ", val);
});
I have all my api get and post requests which need the token. When I make a call like below:
getDashboard() {
if (this.dashboard) {
return Promise.resolve(this.dashboard);
}
return new Promise(resolve => {
this.http
.get(globals.base_prod_api_url + "dashboard", {
headers: {
"Content-Type": globals.content_type,
Authorization: "Bearer " + this.token
}
})
.subscribe(
data => {
this.dashboard = data;
resolve(this.dashboard);
},
error => {
console.log(error);
this.dashboard = error;
return this.dashboard;
}
);
});
}
this.utilService.getDashboard().then(data => {
this.dashboard_data = data;
});
Get request is executed even before the token value is retrieved from Storage. How can I get token first only then make a get request to server?
Upvotes: 0
Views: 1736
Reputation: 2171
i think you should use interceptors to do that.
First you have to add it to your app.module.ts providers :
providers: [
{
provide: HTTP_INTERCEPTORS,
useClass: HttpTokenInterceptor,
multi: true
},
...
],
Then intercept the request and add your token to the headers :
import { Injectable, Inject } from '@angular/core';
import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent, HttpResponse } from '@angular/common/http';
import { JwtService } from '../services/jwt.service';
@Injectable({
providedIn: 'root'
})
export class HttpInterceptorService implements HttpInterceptor {
constructor(
private jwtService: JwtService,
) {}
public intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const headersConfig = {
'Accept': 'application/json',
};
storage.get('token').then((token) => {
headersConfig['Authorization'] = `Bearer ${token}`;
return next.handle(request.clone({
setHeaders: headersConfig
}));
});
}
To go further, you can use the interceptors to catch errors : (401 for example to handle the refresh token)
return next
.handle(request.clone({
setHeaders: headersConfig
}))
.pipe(
catchError(err => {
if (err.status === 401) {
// token is no longer available, refresh it
}
return throwError(err);
})
);
Upvotes: 1
Reputation: 3593
If I were you I'd use Observables rather then Promises. Something like for RXJS 6
import { from } from 'rxjs';
get authToken(): Observable<string> {
return from(storage.get('token')))
}
sendRequest():Observable<ReturnedObject> {
this.authToken.pipe(switchMap(token => {
return this.http
.get(globals.base_prod_api_url + "dashboard", {
headers: {
"Content-Type": globals.content_type,
Authorization: "Bearer " + token
}
})
}))
}
Alternatively ES6 Promises decorators: Async, Await will radically simplify your code. Just don't remember to catch rejected promises via try/catch blocks
Upvotes: 2
Reputation: 361
You might create a private async method in the utils.service.ts which gits the token if the value of the token is undefined and return it. for example :
async getToken(): Promise<string> {
if(!this.token){
this.token = await storage.get('token');
}
return this.token;
}
and mark the other methods as async and 'await' for the token in the headers object.
for example
async getData(){
....
headers: {
"Content-Type": '...',
Authorization: "Bearer " + await this.getToken()
}
....
}
Upvotes: 1