我第一次访问具有解决方案的路径时,不会发送对象请求。访问该页面的唯一方法是确保URL栏中的路径正确(键入或单击链接)并刷新页面而不缓存(在Firefox中按ctrl + shift + r或在Chrome中按ctrl + F5)。
我访问后第一次链接就可以了。
app.config(['$stateProvider', function($stateProvider){
$stateProvider.state('users', {
templateUrl: '/app/Users/templates/users.html',
controller: 'Users',
resolve: {
'users': function(Objects, $stateParams){
return Objects.getUsers();
}
},
url: '^/users'
});
$stateProvider.state('user', {
templateUrl: '/app/Users/templates/user.html',
controller: 'User',
resolve: {
'user': function(Objects, $stateParams){
return Objects.getUser($stateParams.id);
}
},
url: '^/users/:id/'
});
}]);
app.factory('Objects', ['$http', '$q', function($http, $q){
/* Retrieve objects once */
var _cache = {};
function cache(key, promiseGetterFn) {
if (key in _cache) {
return _cache[key];
}
else {
var promise = promiseGetterFn();
_cache[key] = promise;
return promise;
}
}
return {
unsetKey: function(key){
delete _cache[key];
},
getUsers: function() {
return cache('users', function () {
var deferred = $q.defer();
$http.get(HOST + '/api/v1.0/users/all').then(
function (result) {
deferred.resolve(result);
});
return deferred.promise;
});
},
/*
getUsers: function(){
return cache('users', function(){
return $http.get(HOST + '/api/v1.0/users/all').success(
function(data, status, headers, config){
return data.users;
}
);
});
},
*/
/*
getUsers: function(){
return cache('users', function(){
var deferred = $q.defer();
return $http.get(HOST + '/api/v1.0/users/all').then(
function(result){
deferred.resolve(result.data.users);
},
function(status){
deferred.reject(status);
}
);
return deferred.promise;
});
},
*/
getUser: function(id){
return cache('user_' + id, function(){
var deferred = $q.defer();
return $http.get(HOST + '/api/v1.0/user/' + id).then(
function(result){
deferred.resolve(result.data.user);
},
function(status){
deferred.reject(status);
}
);
return deferred.promise;
});
},
};
}]);
app.run(['$rootScope', '$location', 'LocalService', function($rootScope, $location, LocalService){
$rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams){
if (!toState.publicAccess && !LocalService.get('loggedIn')){
/* Store the route they were trying to access */
LocalService.set('next', $location.path());
$location.path('/login');
}
});
}]);
登录代码后重定向
app.factory('AuthInterceptor', ['$q', '$injector', '$location', 'LocalService', function($q, $injector, $location, LocalService){
/* Send Authorization in the header of each http request if there is a token */
return {
request: function(config){
if (LocalService.get('token')){
/* Using btoa to do Base64 */
/* LocalService.password is only used on login to get token and will be empty ('') when using the token */
config.headers.Authorization = 'Basic ' + btoa(LocalService.get('token') + ':' + LocalService.get('password'));
}
return config;
},
responseError: function(response){
if(response.status === 401 || response.status === 403){
/* Log the user out */
LocalService.unset('loggedIn');
LocalService.unset('token');
LocalService.unset('user');
$location.path('/login');
}
return $q.reject(response);
}
};
}]);
app.config(['$httpProvider', function($httpProvider){
$httpProvider.interceptors.push('AuthInterceptor');
}]);
app.run(['$rootScope', '$location', 'LocalService', function($rootScope, $location, LocalService){
$rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams){
if (!toState.publicAccess && !LocalService.get('loggedIn')){
/* Store the route they were trying to access */
LocalService.set('next', $location.path());
$location.path('/login');
}
});
}]);
app.controller('Login', ['$scope', '$http', '$location', 'growl', 'LocalService',
function($scope, $http, $location, growl, LocalService){
$scope.email = '';
$scope.password = '';
$scope.submitLogin = function submitLogin(){
LocalService.set('token', $scope.email);
LocalService.set('password', $scope.password);
$http.get(HOST + '/api/v1.0/token').
success(function(data, status, headers, config) {
LocalService.set('token', data.token);
LocalService.set('loggedIn', true);
LocalService.set('password', '');
/* Set current user */
$http.get(HOST + '/api/v1.0/authenticate').then(function(result) {
LocalService.set('user', JSON.stringify(result.data));
if (LocalService.get('next')){
var next = LocalService.get('next');
LocalService.unset('next');
console.log(next);
$location.path(next);
}
else{
$location.path('/');
}
});
}
).
error(function(data, status, headers, config) {
/* invalid credentials growl */
growl.addErrorMessage('Invalid username or password.');
}
);
};
}
]);
答案 0 :(得分:0)
我首先想到的是解析的对象只能在硬加载时解析。一旦从index.html实例化了应用程序,部分视图可能没有注册对象是promises。我会尝试从工厂(api)实际承诺返回对象。现在我从未见过像你这样的承诺,但我没有看到任何'deferred.resolve'或'deffered.reject'。例如:
return {
getBundles: function(){
return cache('bundles', function(){
var deffered = $q.defer
return $http.get(HOST + '/api/v1.0/bundles/all').success(
function(data, status, headers, config){
deferred.resolve(data.bundles);
}.error(function(status){
deferred.reject(status);
)};
return deferred.promise;
});
},
}
在执行此操作时,我还建议您在将对象绑定到视图之前将对象返回到javascript对象。这将在控制器中完成,并将“束”注入控制器。
var thisBundle = bundles.data.bundles;
thisBundle.then(function(data){
$scope.bundles = data;
});
我发现的另一个解决方案是在路由中包含所有项目。试试这个:
resolve: {
'allProducts' : function(){
var theResolvePromise = $q.defer();
theResolvePromise.resolve({
bundles: ['Objects', function(Objects){
return Objects.getBundles();
}],
products: ['Objects', function(Objects){
return Objects.getProducts();
}],
technologies: ['Objects', function(Objects){
return Objects.getTechnologies();
}],
deliveryCategories: ['Objects', function(Objects){
return Objects.getDeliveryCategories();
}],
});
return theResolvePromise.promise;
};
}
}).
然后您将在控制器中访问此参数并传递参数。 取自:http://www.undefinednull.com/2014/02/17/resolve-in-angularjs-routes-explained-as-story/
希望这有帮助,
帕特里克
答案 1 :(得分:0)
试试这个。我没有测试它,所以它可能不完美,但也许它会帮助你找到正确的方向。
app.factory('Objects', ['$http', function($http){
var _cache = {};
function cache(key, getterFn) {
if (_cache[key] == null) {
_cache[key] = getterFn();
_cache[key].then(function (result) {
_cache[key] = result;
});
}
return _cache[key];
}
return {
unsetKey: function(key){
delete _cache[key];
},
getUsers: function() {
return cache('users', function () {
return $http.get(HOST + '/api/v1.0/users/all');
});
},
getUser: function(id){
return cache('user_' + id, function() {
return $http.get(HOST + '/api/v1.0/user/' + id).then(function (result) {
return result.data.user;
});
});
},
};
}]);
$http.get
返回一个在请求完成时解析的promise。从.then()
函数返回值会将该值弹出到链中的下一个.then()
。 UI-Router解析后会自动解包承诺。如果给出其他任何东西,它只会返回它。承诺不会自动解开Angular 1.2+,因此当您在缓存中工作时,您需要自己打开它。
答案 2 :(得分:0)
你的问题是2部分。
1)为什么我的第一个决心不解决状态的决心?
您第一次返回"承诺履行履行数据的承诺"。这就像一个链式的承诺。如果您返回了获取数据的承诺,则需要一个额外的$摘要周期来解决此问题。 $ http.get()返回一个promise。
In AngularJS the results of promise resolution are propagated asynchronously, inside a $digest cycle. So, callbacks registered with then() will only be called upon entering a $digest cycle.
同时检查出来
Angular JS: Chaining promises and the digest cycle
2)你可以改变什么来解决这个问题?
你可以做两件事 只需返回$ http.get(),因为这本身就是一个承诺。 为什么要缓存一个promise对象?您应该缓存实际数据。 使用$ resource和$ http,您可以传递{cache:true},结果将被缓存。或者,如果你想控制你可能想要使用$ cacheFactory。在这种情况下,您可以将实际结果放在缓存中,而不是promise对象。