显示多个异步Ajax调用的等待Gif

时间:2014-09-28 05:02:59

标签: javascript jquery ajax angularjs

我正在使用AngularJS和一些jQuery插件创建一个页面,其中angular-js控制器通过异步调用ajax调用一些servlet方法来初始化其模型。我想在第一个ajax调用开始时显示一个加载gif,并在最后一个ajax调用结束时隐藏它。

由于我不知道哪个是最后一次ajax调用,我不知道在哪里放置指令隐藏加载gif。我怎样才能实现这种行为?

我想要的代码示例:

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();
}

我希望你能理解我的问题并知道如何实现这一目标。

4 个答案:

答案 0 :(得分:2)

查看http://chieffancypants.github.io/angular-loading-bar/等进度条,可以在发出http请求时显示进度。它基本上是一个http拦截器,它跟踪http请求的数量,并相应地显示\隐藏进度条。

如果要解决此特定方案,可以使用$ q.all来实现此行为。首先,对于所有init *函数,返回http promise

 $scope.initData1 = function() {
        /* is this the first call? then show the gif */
        var promise = $http(...);
        promise.success(function(data) { // handle data});
        return promise;
    }

现在在调用代码中只需执行

//show animation
$q.all([$sope.initData1(),$sope.initData2(),$sope.initData3()]).then(function(responseArray) {
   //hide animation
})

答案 1 :(得分:1)

如何:声明一个服务,您可以在其中注册待处理任务,然后声明它们已完成。

myApp.factory('pendingService', [function () {
  var pendingTasksCount = 0;

  return {
    anyPending: function () {
      return pendingTasksCount > 0;
    },
    registerNewTask: function () {
      pendingTasksCount += 1;
      return function declareTaskDone() {
        pendingTasksCount -= 1;
      }
    }
  };
}]);

然后在你的控制器中:

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();
});

在HTML中:

<img src="mygifurl" alt="loading" ng-show="showGif()"/>

如果您需要此行为是本地行为而非全局行为,则可以使用同一工厂创建本地对象。

答案 2 :(得分:0)

您可以使用$.active来检查正在进行的活动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();
}

答案 3 :(得分:0)

我会使用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>

您需要修改$ scope。$ apply函数上下文中的范围(在此特定示例中),否则您的视图将不会更新(有关发生这种情况的更多信息,请参阅:http://www.jeffryhouser.com/index.cfm/2014/6/2/How-do-I-run-code-when-a-variable-changes-with-AngularJS)。如果你使用promises,你可以避免这个问题,但我相信使用ngClass是修改视图的有角度的方法。