I am making a page with AngularJS and some jQuery plugins in which the angular-js controller initializes its model by calling some servlet methods via ajax asynchronously. I want to show a loading gif when the first ajax call starts and hide it when the last ajax call finishes.
我正在用AngularJS和一些jQuery插件创建一个页面,其中angular-js控制器通过异步调用一些servlet方法初始化其模型。我想在第一个ajax调用开始时显示加载gif,在最后一个ajax调用结束时隐藏它。
Since I don't know which will be the last ajax call to finish, I cannot know where to place the instructions to hide the loading gif. How can I achieve this behavior?
由于我不知道哪个将是最后一次ajax调用,所以我不知道在哪里放置指令来隐藏加载gif。我如何实现这种行为?
A code example of what i want:
我想要的代码示例:
myApp.controller("adminCtrl", function($scope, $http) {
$scope.initData1 = function() {
/* is this the first call? then show the gif */
$http(...).success(function() { /* is this the last response received? then hide the gif */});
}
$scope.initData2 = function() {
/* is this the first call? then show the gif */
$http(...).success(function() { /* is this the last response received? then hide the gif */});
}
$scope.initData3 = function() {
/* is this the first call? then show the gif */
$http(...).success(function() { /* is this the last response received? then hide the gif */});
}
initData1();
initData2();
initData3();
}
I hope you understand my problem and know any way to achieve this.
我希望你能理解我的问题,并知道实现这个目标的方法。
4 个解决方案
#1
1
How about this : declare a service where you can register pending tasks, then declare them done.
如何:声明一个服务,您可以在其中注册挂起的任务,然后声明它们已经完成。
myApp.factory('pendingService', [function () {
var pendingTasksCount = 0;
return {
anyPending: function () {
return pendingTasksCount > 0;
},
registerNewTask: function () {
pendingTasksCount += 1;
return function declareTaskDone() {
pendingTasksCount -= 1;
}
}
};
}]);
Then in your controller :
然后在控制器中:
myApp.controller("adminCtrl", function($scope, $http, pendingService) {
// expose "any pending task" property in scope
$scope.showGif = pendingService.anyPending;
$scope.initData1 = function() {
var declareDone = pendingService.registerNewTask();
$http(...).success(function() {
// do stuff
// ...
declareDone();
});
};
$scope.initData2 = function() {
var declareDone = pendingService.registerNewTask();
$http(...).success(function() {
// do stuff
// ...
declareDone();
});
};
$scope.initData3 = function() {
var declareDone = pendingService.registerNewTask();
$http(...).success(function() {
// do stuff
// ...
declareDone();
});
};
initData1();
initData2();
initData3();
});
And in the HTML :
在HTML中:
<img src="mygifurl" alt="loading" ng-show="showGif()"/>
If you need this behavior to be local, not global, you can just use the same factory to create a local object.
如果您需要这个行为是局部的,而不是全局的,您可以使用同一个工厂来创建一个局部对象。
#2
2
Look at progress bar such as http://chieffancypants.github.io/angular-loading-bar/ that can show progress when ever a http request is made. It is basically a http interceptor that tracks the number the http requests and show\hides the progress bar accordingly.
查看进度条,如http://chieffancypants.github。io/angular-loading-bar/当发出http请求时可以显示进程。它基本上是一个http拦截器,跟踪http请求的数量并相应地显示\隐藏进度条。
If you want to solve this specific scenario, you can use $q.all to achieve the behaviour. Firstly for all init* functions return the http promise
如果您想要解决这个特定的场景,可以使用$q。都是为了实现行为。首先,所有init*函数都返回http承诺。
$scope.initData1 = function() {
/* is this the first call? then show the gif */
var promise = $http(...);
promise.success(function(data) { // handle data});
return promise;
}
Now in the calling code just do
现在在调用代码中。
//show animation
$q.all([$sope.initData1(),$sope.initData2(),$sope.initData3()]).then(function(responseArray) {
//hide animation
})
#3
0
you can use $.active to check how many active ajax requests are in progress.
你可以使用美元。活动以检查有多少活动的ajax请求正在进行中。
myApp.controller("adminCtrl", function($scope, $http) {
$scope.initData1 = function() {
if($.active==0){
//this is the last active ajax request
}
/* is this the first call? then show the gif */
$http(...).success(function() { /* is this the last response received? then hide the gif */});
}
$scope.initData2 = function() {
if($.active==0){
//this is the last active ajax request
}
/* is this the first call? then show the gif */
$http(...).success(function() { /* is this the last response received? then hide the gif */});
}
$scope.initData3 = function() {
if($.active==0){
//this is the last active ajax request
}
/* is this the first call? then show the gif */
$http(...).success(function() { /* is this the last response received? then hide the gif */});
}
initData1();
initData2();
initData3();
}
#4
0
I would use ngClass for this, and a counter variable, e.g.
我将使用ngClass来做这个,还有一个计数器变量。
<html ng-app="testApp">
<head>
<style class="text/css">
.showing {
/* instead of this, you can add your gif here */
background: #f0f;
}
</style>
</head>
<body ng-controller="TestController">
<div class="test" ng-class="{'showing': count > 0 && count < 3}">
Count: {{count}}
</div>
<script type="text/javascript" src="angular.min.js"></script>
<script type="text/javascript">
(function() {
var testApp = angular.module("testApp", []);
testApp.controller("TestController", function($scope) {
$scope.count = 0;
var timeout = function(t) {
// this represents your ajax callbacks
setTimeout(function() {
$scope.$apply(function() {
$scope.count = $scope.count + 1;
});
}, t * 1000);
};
timeout(1);
timeout(2);
timeout(3);
});
})();
</script>
</body>
</html>
You need to modify the scope inside the $scope.$apply function context (in this particular example), or your view won't update (for more information on why this happens, see: http://www.jeffryhouser.com/index.cfm/2014/6/2/How-do-I-run-code-when-a-variable-changes-with-AngularJS). If you use promises, you may be able to avoid this problem, but I believe using ngClass is the angular way to modify the view.
您需要修改$范围内的范围。$apply函数上下文(在本例中),或者您的视图不会更新(关于为什么会发生这种情况的更多信息,请参见:http://www.jeffryhouser.com/index.cfm4//2012/2/how-runcode -when- variable-change -with- angularjs))。如果您使用承诺,您可能可以避免这个问题,但是我相信使用ngClass是修改视图的角度方式。
#1
1
How about this : declare a service where you can register pending tasks, then declare them done.
如何:声明一个服务,您可以在其中注册挂起的任务,然后声明它们已经完成。
myApp.factory('pendingService', [function () {
var pendingTasksCount = 0;
return {
anyPending: function () {
return pendingTasksCount > 0;
},
registerNewTask: function () {
pendingTasksCount += 1;
return function declareTaskDone() {
pendingTasksCount -= 1;
}
}
};
}]);
Then in your controller :
然后在控制器中:
myApp.controller("adminCtrl", function($scope, $http, pendingService) {
// expose "any pending task" property in scope
$scope.showGif = pendingService.anyPending;
$scope.initData1 = function() {
var declareDone = pendingService.registerNewTask();
$http(...).success(function() {
// do stuff
// ...
declareDone();
});
};
$scope.initData2 = function() {
var declareDone = pendingService.registerNewTask();
$http(...).success(function() {
// do stuff
// ...
declareDone();
});
};
$scope.initData3 = function() {
var declareDone = pendingService.registerNewTask();
$http(...).success(function() {
// do stuff
// ...
declareDone();
});
};
initData1();
initData2();
initData3();
});
And in the HTML :
在HTML中:
<img src="mygifurl" alt="loading" ng-show="showGif()"/>
If you need this behavior to be local, not global, you can just use the same factory to create a local object.
如果您需要这个行为是局部的,而不是全局的,您可以使用同一个工厂来创建一个局部对象。
#2
2
Look at progress bar such as http://chieffancypants.github.io/angular-loading-bar/ that can show progress when ever a http request is made. It is basically a http interceptor that tracks the number the http requests and show\hides the progress bar accordingly.
查看进度条,如http://chieffancypants.github。io/angular-loading-bar/当发出http请求时可以显示进程。它基本上是一个http拦截器,跟踪http请求的数量并相应地显示\隐藏进度条。
If you want to solve this specific scenario, you can use $q.all to achieve the behaviour. Firstly for all init* functions return the http promise
如果您想要解决这个特定的场景,可以使用$q。都是为了实现行为。首先,所有init*函数都返回http承诺。
$scope.initData1 = function() {
/* is this the first call? then show the gif */
var promise = $http(...);
promise.success(function(data) { // handle data});
return promise;
}
Now in the calling code just do
现在在调用代码中。
//show animation
$q.all([$sope.initData1(),$sope.initData2(),$sope.initData3()]).then(function(responseArray) {
//hide animation
})
#3
0
you can use $.active to check how many active ajax requests are in progress.
你可以使用美元。活动以检查有多少活动的ajax请求正在进行中。
myApp.controller("adminCtrl", function($scope, $http) {
$scope.initData1 = function() {
if($.active==0){
//this is the last active ajax request
}
/* is this the first call? then show the gif */
$http(...).success(function() { /* is this the last response received? then hide the gif */});
}
$scope.initData2 = function() {
if($.active==0){
//this is the last active ajax request
}
/* is this the first call? then show the gif */
$http(...).success(function() { /* is this the last response received? then hide the gif */});
}
$scope.initData3 = function() {
if($.active==0){
//this is the last active ajax request
}
/* is this the first call? then show the gif */
$http(...).success(function() { /* is this the last response received? then hide the gif */});
}
initData1();
initData2();
initData3();
}
#4
0
I would use ngClass for this, and a counter variable, e.g.
我将使用ngClass来做这个,还有一个计数器变量。
<html ng-app="testApp">
<head>
<style class="text/css">
.showing {
/* instead of this, you can add your gif here */
background: #f0f;
}
</style>
</head>
<body ng-controller="TestController">
<div class="test" ng-class="{'showing': count > 0 && count < 3}">
Count: {{count}}
</div>
<script type="text/javascript" src="angular.min.js"></script>
<script type="text/javascript">
(function() {
var testApp = angular.module("testApp", []);
testApp.controller("TestController", function($scope) {
$scope.count = 0;
var timeout = function(t) {
// this represents your ajax callbacks
setTimeout(function() {
$scope.$apply(function() {
$scope.count = $scope.count + 1;
});
}, t * 1000);
};
timeout(1);
timeout(2);
timeout(3);
});
})();
</script>
</body>
</html>
You need to modify the scope inside the $scope.$apply function context (in this particular example), or your view won't update (for more information on why this happens, see: http://www.jeffryhouser.com/index.cfm/2014/6/2/How-do-I-run-code-when-a-variable-changes-with-AngularJS). If you use promises, you may be able to avoid this problem, but I believe using ngClass is the angular way to modify the view.
您需要修改$范围内的范围。$apply函数上下文(在本例中),或者您的视图不会更新(关于为什么会发生这种情况的更多信息,请参见:http://www.jeffryhouser.com/index.cfm4//2012/2/how-runcode -when- variable-change -with- angularjs))。如果您使用承诺,您可能可以避免这个问题,但是我相信使用ngClass是修改视图的角度方式。