我正在使用AngularJS的$http服务来进行Ajax请求。
如何在Ajax请求执行时显示旋转GIF(或另一种类型的忙碌指示器)?
我在AngularJS文档中没有看到类似ajaxstartevent的东西。
我正在使用AngularJS的$http服务来进行Ajax请求。
如何在Ajax请求执行时显示旋转GIF(或另一种类型的忙碌指示器)?
我在AngularJS文档中没有看到类似ajaxstartevent的东西。
当前回答
简单的方法没有拦截器或jQuery
这是一种显示旋转器的简单方法,不需要第三方库、拦截器或jQuery。
在控制器中设置和重置标志位。
function starting() {
//ADD SPINNER
vm.starting = true;
$http.get(url)
.then(function onSuccess(response) {
vm.data = response.data;
}).catch(function onReject(errorResponse) {
console.log(errorResponse.status);
}).finally(function() {
//REMOVE SPINNER
vm.starting = false;
});
};
在HTML中,使用标记:
<div ng-show="vm.starting">
<img ng-src="spinnerURL" />
</div>
<div ng-hide="vm.starting">
<p>{{vm.data}}</p>
</div>
vm。当XHR开始时设置为true,当XHR完成时清除。
其他回答
分享来自@bulltorious的精彩答案的我的版本,更新到更新的angular构建(我使用了1.5.8版本的代码),还加入了@JMaylin的想法,使用计数器来健壮地处理多个并发请求,以及选择跳过显示小于最小毫秒数的请求动画:
var app = angular.module('myApp');
var BUSY_DELAY = 1000; // Will not show loading graphic until 1000ms have passed and we are still waiting for responses.
app.config(function ($httpProvider) {
$httpProvider.interceptors.push('busyHttpInterceptor');
})
.factory('busyHttpInterceptor', ['$q', '$timeout', function ($q, $timeout) {
var counter = 0;
return {
request: function (config) {
counter += 1;
$timeout(
function () {
if (counter !== 0) {
angular.element('#busy-overlay').show();
}
},
BUSY_DELAY);
return config;
},
response: function (response) {
counter -= 1;
if (counter === 0) {
angular.element('#busy-overlay').hide();
}
return response;
},
requestError: function (rejection) {
counter -= 1;
if (counter === 0) {
angular.element('#busy-overlay').hide();
}
return rejection;
},
responseError: function (rejection) {
counter -= 1;
if (counter === 0) {
angular.element('#busy-overlay').hide();
}
return rejection;
}
}
}]);
显示不同url更改之间加载的另一个解决方案是:
$rootScope.$on('$locationChangeStart', function() {
$scope.loading++;
});
$rootScope.$on('$locationChangeSuccess', function() {
$timeout(function() {
$scope.loading--;
}, 300);
});
然后在标记中用ng-show="loading"切换旋转器。
如果你想在ajax请求中显示它,只需添加$scope。当请求开始和结束时加载++,添加$scope.loading——。
这对我来说很管用:
HTML:
<div id="loader" class="ng-hide" ng-show="req.$$state.pending">
<img class="ajax-loader"
width="200"
height="200"
src="/images/spinner.gif" />
</div>
角:
$scope.req = $http.get("/admin/view/"+id).success(function(data) {
$scope.data = data;
});
当$http返回的承诺是未决的,ng-show将评估它是“真实的”。一旦承诺被解决,这将自动更新…这正是我们想要的。
如果你想为每个HTTP请求调用显示加载器,那么你可以使用angular interceptor来管理HTTP请求调用。
下面是一个示例代码
<body data-ng-app="myApp">
<div class="loader">
<div id="loader"></div>
</div>
<script>
var app = angular.module("myApp", []);
app.factory('httpRequestInterceptor', ['$rootScope', '$location', function ($rootScope, $location) {
return {
request: function ($config) {
$('.loader').show();
return $config;
},
response: function ($config) {
$('.loader').hide();
return $config;
},
responseError: function (response) {
return response;
}
};
}]);
app.config(['$stateProvider', '$urlRouterProvider', '$httpProvider',
function ($stateProvider, $urlRouterProvider, $httpProvider) {
$httpProvider.interceptors.push('httpRequestInterceptor');
}]);
</script>
</body>
如果我们知道DRY的概念,那么所有的答案都是复杂的,或者需要在每个请求上设置一些变量,这是非常错误的做法。这里是一个简单的拦截器的例子,当ajax启动时,我将鼠标设置为等待,当ajax结束时设置为自动。
$httpProvider.interceptors.push(function($document) {
return {
'request': function(config) {
// here ajax start
// here we can for example add some class or show somethin
$document.find("body").css("cursor","wait");
return config;
},
'response': function(response) {
// here ajax ends
//here we should remove classes added on request start
$document.find("body").css("cursor","auto");
return response;
}
};
});
代码必须添加到应用程序配置app.config中。我展示了如何改变鼠标加载状态,但在那里,它是可以显示/隐藏任何加载器内容,或添加,删除一些css类显示加载器。
拦截器将在每次ajax调用上运行,因此不需要创建特殊的布尔变量($scope. js)。加载=true/false等)在每个HTTP调用。