Javascript 首先,AngularJS解决方案不起作用
我第一次访问带有解析的路由时,不会发送对对象的请求。访问页面的唯一方法是确保url栏中的路由正确(键入或单击链接),并在不缓存的情况下刷新页面(Firefox中的ctrl+shift+r或Chrome中的ctrl+F5) 在我访问它之后,第一次链接将起作用Javascript 首先,AngularJS解决方案不起作用,javascript,angularjs,Javascript,Angularjs,我第一次访问带有解析的路由时,不会发送对对象的请求。访问页面的唯一方法是确保url栏中的路由正确(键入或单击链接),并在不缓存的情况下刷新页面(Firefox中的ctrl+shift+r或Chrome中的ctrl+F5) 在我访问它之后,第一次链接将起作用 app.config(['$stateProvider', function($stateProvider){ $stateProvider.state('users', { templateUrl: '/app/Users/t
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.');
}
);
};
}
]);
我对此的第一个想法是,解析对象仅在硬负载下解析。从index.html实例化应用程序后,部分视图可能不会记录对象是否存在。我将尝试使工厂(api)返回的对象成为实际的承诺。现在,我从未见过像你这样的承诺,但我没有看到任何“推迟。解决”或“改变。拒绝”。例如:
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对象。这将在控制器中完成,并将“bundle”注入控制器
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;
};
}
}).
然后,您将在控制器中通过传递的参数访问该文件。
检索自:
希望这有帮助
帕特里克试试这个。我没有测试它,所以它可能不是完美的,但它可能会帮助你指向正确的方向
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
返回在请求完成时解析的承诺。从.then()
函数返回一个值将把该值弹出到链中的下一个.then()
中。UI路由器的解决方案会自动取消承诺(如果给定)。如果给了其他任何东西,它只会返回它。承诺不会在Angular 1.2+中自动展开,因此当您在缓存中工作时,您需要自己将其展开。您的问题分为两部分
1) 为什么我的第一个决心不是为州下决心
第一次返回“承诺兑现承诺兑现数据”时。这就像一个被锁住的承诺。如果您返回获取数据的承诺,则需要额外一个$digest周期来解决此问题$get()返回一个承诺
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.
也看看这个
2) 您可以更改什么来解决问题
你可以做两件事
只需返回$http.get(),因为这本身就是一个承诺。
为什么缓存承诺对象?您应该缓存实际数据。
另外,使用$resource和$http,您可以传递{cache:true},结果将被缓存。或者,如果您希望控制,您可能希望使用$cacheFactory。在这种情况下,可以将实际结果放置在缓存中,而不是promise对象中 没有控制台错误,只是没有请求。请记住也要在服务器端进行身份验证…我在服务器端进行身份验证,只要我使用缓存刷新,或者这是第二次或更长时间,就可以工作。这可能与您的问题无关,但如果a)使用承诺链接,您的代码可以更短更简单,因此,不要通过
$q.defer
创建承诺,而是使用成功+错误回调的返回值;b) 您使用库函数来进行缓存,或者使用未定义的I'm get deferred。我认为在.error()中。我也在错误发生之前结束了成功。您是否为包装返回的函数实例化了“$q”?确保您有注入。上面的差异显示为JSHint未使用。我不是百分之百地确定回报应该放在哪里,通常是放在里面。我确实有“$q”依赖项。我用另一个解决方案更新了答案,并在返回时做了更多解释。看看这是否有效。我还在一个网站上附加了一个URL,它很好地解释了我在学习时使用的URL。$http
调用了返回承诺。这似乎有效,只是它在登录后中断了我的重定向。我已经在我的帖子中添加了这方面的代码。如果我将{cache:true}添加到$http.get()请求中,当我在数据库中添加一个新项并且不再想使用缓存结果时,如何删除缓存?var defaultCache=$cacheFactory('$http');但是,您应该拥有自己的缓存。我的观点是使用$cachefactory,而不是重新发明。您可以用自己的缓存替换默认缓存,这样您就可以拥有更多的控制权。根据Angular文档,价格为$http。通过更新$http.defaults.cache属性,可以将默认缓存更改为新对象(使用$cacheFactory构建)。所有将其缓存属性设置为true的请求现在都将使用此缓存对象。在应用程序级别的config/run中执行此操作一次。