Currently I'm trying to cache a user's information. I give you guys a scenario of what is happening.
a user is trying to log in with an account A. Account A's name appears on the navbar. After that user log out and tries to log in with an account B, on the navbar itself the name is still belongs to account A's name.
The code
service.js
.factory('Auth', function($http, $q, AuthToken) {
// create auth factory object
var authFactory = {};
// log a user in
authFactory.login = function(username, password) {
// return the promise object and its data
return $http.post('/api/login', {
username: username,
password: password
})
.success(function(data) {
AuthToken.setToken(data.token);
return data;
});
};
// log a user out by clearing the token
authFactory.logout = function() {
// clear the token
AuthToken.setToken();
};
// check if a user is logged in
// checks if there is a local token
authFactory.isLoggedIn = function() {
if (AuthToken.getToken())
return true;
else
return false;
};
// get the logged in user
authFactory.getUser = function() {
if (AuthToken.getToken())
return $http.get('/api/me', {cache: true});
else
return $q.reject({ message: 'User has no token.' });
};
// return auth factory object
return authFactory;
})
// ===================================================
// factory for handling tokens
// inject $window to store token client-side
// ===================================================
.factory('AuthToken', function($window) {
var authTokenFactory = {};
// get the token out of local storage
authTokenFactory.getToken = function() {
return $window.localStorage.getItem('token');
};
// function to set token or clear token
// if a token is passed, set the token
// if there is no token, clear it from local storage
authTokenFactory.setToken = function(token) {
if (token)
$window.localStorage.setItem('token', token);
else
$window.localStorage.removeItem('token');
};
return authTokenFactory;
})
// ===================================================
// application configuration to integrate token into requests
// ===================================================
.factory('AuthInterceptor', function($q, $location, AuthToken) {
var interceptorFactory = {};
// this will happen on all HTTP requests
interceptorFactory.request = function(config) {
// grab the token
var token = AuthToken.getToken();
// if the token exists, add it to the header as x-access-token
if (token)
config.headers['x-access-token'] = token;
return config;
};
// happens on response errors
interceptorFactory.responseError = function(response) {
// if our server returns a 403 forbidden response
if (response.status == 403)
$location.path('/login');
// return the errors from the server as a promise
return $q.reject(response);
};
return interceptorFactory;
});
controller.js
angular.module('mainCtrl', [])
.controller('MainController', function($rootScope, $location, Auth) {
var vm = this;
// get info if a person is logged in
vm.loggedIn = Auth.isLoggedIn();
// check to see if a user is logged in on every request
$rootScope.$on('$routeChangeStart', function() {
vm.loggedIn = Auth.isLoggedIn();
// get user information on page load
Auth.getUser()
.then(function(data) {
vm.user = data.data;
});
});
// function to handle login form
vm.doLogin = function() {
vm.processing = true;
// clear the error
vm.error = '';
Auth.login(vm.loginData.username, vm.loginData.password)
.success(function(data) {
vm.processing = false;
// get user information on page load
Auth.getUser()
.then(function(data) {
vm.user = data.data;
});
// if a user successfully logs in, redirect to users page
if (data.success)
$location.path('/');
else
vm.error = data.message;
});
};
// function to handle logging out
vm.doLogout = function() {
Auth.logout();
$location.path('/logout');
};
});
index.html
<ul class="nav navbar-nav navbar-right">
<li ng-if="!main.loggedIn"><a href="/login">Login</a></li>
<li ng-if="main.loggedIn"><a href="#">Hello {{ main.user.username }}</a></li>
<li ng-if="main.loggedIn"><a href="#" ng-click="main.doLogout()">Logout</a></li>
<li><a href=""><button class="btn btn-primary">Write</button></a></li>
</ul>
So basically my assumption of the problem lies in the service.js where i added cache: true. Do i need to add some logic to it?
There are two different caches that may be involved in your app. First it's the angular cache which you have set below {cache: true}
This cache is only there for the duration of the app, once you leave or reload the page, it's gone!
The other cache which is the browser cache is a little more complex to deal with. Note this has no relationship with the Angular cache, so if this is your problem simply turning off {cache: false} wont help. To prevent cache you will need to send a list of different caching headers in your restful API and it may not always work.
The easiest way to prevent cache is to add a version to your url which doesnt actually affect your results but tricks your browser into thinking that it's a different url. This is referred to as Cache Busting.
The easiest way to cache bust is to add a Math.Random() to append to the url. The chances of Math.Random to be the same is probably in the billions.
However, if you want a better way to do it specific for your app, you could append the username to your url. This way it will cache for the same users which means you are actually taking advantage of the caching mechanism and not getting tied down by it!