Reputation: 197
I am currently building an application with Ionic 2 and using the Storage plugin to hold my values which are pretty much just an API Token and user profile since the application pulls all data from an API.
I am testing the application via ionic serve
because no native functions are used but now I am facing the problem that every time I store a value in the Storage the value is not accessible until I reload the app which is kind of annoying because after the user logs in he gets redirected to a page that requires the API token which is not available until I reload the app so the whole thing gets stuck in a loop.
Ionic Storage is using IndexedDB in the browser where I can see that the values have been stored when I check them with Chrome Developer tools.
I have been trying to figure out the issue but can't find any reason why the storage values are not available until reloading the app.
import { Injectable } from '@angular/core';
import { Storage } from '@ionic/storage';
import { HttpClientService } from './http-client-service';
import 'rxjs/add/operator/map';
@Injectable()
export class AuthService {
constructor(public events: Events, public storage: Storage, public http: HttpClientService) {
//
}
login(user) {
var response = this.http.post('login', {
email: user.email,
password: user.password,
});
response.subscribe(data => {
this.storage.set('api_token', data.token);
console.log('raw : ' + data.token); // shows the api token
this.storage.get('api_token').then((value) => {
console.log('storage : '+ value); // is empty...
});
});
return response;
};
}
Edit: I managed to track down the issue to the storage running async which results in the token not being added to the headers.
createAuthorizationHeader(headers: Headers) {
// this does add the header in time
localStorage.setItem('api_token', 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOi8vYXBpLndpaHplLmRldi9sb2dpbiIsImlhdCI6MTQ4MTE4MzQyOCwiZXhwIjoxNDgxMTg3MDI4LCJuYmYiOjE0ODExODM0MjgsImp0aSI6IjdlNTE1WUEwWmE4NWc2QjUiLCJzdWIiOiIxIiwidXNlciI6eyJpZCI6MX19.T4KpqgCB8xU79vKyeLG4CJ0OHLpVI0j37JKIBJ_0CC4');
headers.append('Authorization', 'Bearer ' + localStorage.getItem('api_token'));
// this does not add the header in time
return this.storage.get('api_token').then((value) => {
headers.append('Authorization', 'Bearer ' + value);
});
}
getHeaders(path) {
let headers = new Headers();
headers.set('Accept', 'application/json');
headers.set('Content-Type', 'application/json');
if(!this.isGuestRoute(path)) {
this.createAuthorizationHeader(headers);
}
return new RequestOptions({ headers: headers });
}
get(path: string) {
return this._http.get(this.actionUrl + path, this.getHeaders(path))
.map(res => res.json())
.catch(this.handleError);
}
Upvotes: 4
Views: 2509
Reputation: 7719
Alright, looked in the ionic docs and I do understand why you put them both underneath eachother since they also display it like that in the docs.
But Storage.set(key, value)
:
Returns: Promise that resolves when the value is set
This means that you cannot use it the way you are using it (hence why they added a comment with //or ....
Since resolving a Promise is asynchronous.
If you want to use the value like you're currently using it (which seems a bit odd but probably for you to test if the value is set correctly) you should use
this.storage.set('api_token', data.token).then(() => {
this.storage.get('api_token').then((value) => {
console.log('storage : '+ value); // is empty...
});
});
console.log('raw : ' + data.token); // shows the api token
If you would like some more information about why this happens, check out this SO answer (I prefer second one) Asynchronous vs synchronous execution, what does it really mean?
Upvotes: 3