Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/jquery/80.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 显示多个异步Ajax调用的等待Gif_Javascript_Jquery_Ajax_Angularjs - Fatal编程技术网

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

Javascript 显示多个异步Ajax调用的等待Gif,javascript,jquery,ajax,angularjs,Javascript,Jquery,Ajax,Angularjs,我正在用AngularJS和一些jQuery插件制作一个页面,AngularJS控制器通过ajax异步调用一些servlet方法来初始化其模型。我想在第一个ajax调用开始时显示加载gif,在最后一个ajax调用结束时隐藏它 因为我不知道哪一个将是最后一个ajax调用完成,所以我不知道在哪里放置隐藏加载gif的指令。我如何实现这种行为 我想要的代码示例: myApp.controller("adminCtrl", function($scope, $http) { $scope.init

我正在用AngularJS和一些jQuery插件制作一个页面,AngularJS控制器通过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();
}

我希望您理解我的问题,并知道实现这一点的任何方法。

如何:声明一个可以注册挂起任务的服务,然后声明它们已完成

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()"/>


如果您需要这种行为是本地的,而不是全局的,您可以使用同一个工厂来创建本地对象。

查看进度条,它可以在发出http请求时显示进度。它基本上是一个http拦截器,跟踪http请求的数量,并相应地显示\隐藏进度条

如果要解决此特定场景,可以使用$q.all实现该行为。首先,对于所有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;
    }
现在在调用代码中,只需执行以下操作

//show animation
$q.all([$sope.initData1(),$sope.initData2(),$sope.initData3()]).then(function(responseArray) {
   //hide animation
})
您可以使用检查正在进行的活动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();
}

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

.展示{
/*您可以在此处添加gif,而不是此选项*/
背景:#f0f;
}
计数:{{Count}
(功能(){
var testApp=angular.module(“testApp”,[]);
testApp.controller(“TestController”,函数($scope){
$scope.count=0;
变量超时=函数(t){
//这表示您的ajax回调
setTimeout(函数(){
$scope.$apply(函数(){
$scope.count=$scope.count+1;
});
},t*1000);
};
超时(1);
超时(2);
超时(3);
});
})();

您需要修改$scope.$apply函数上下文中的作用域(在此特定示例中),否则视图将不会更新(有关发生此情况的原因的详细信息,请参阅:)。如果使用Promissions,您可能可以避免这个问题,但我相信使用ngClass是修改视图的角度方法。

如果这样做有效,惯用的角度方法应该是在IMHO范围内公开$.active属性。我更喜欢角度相关的解决方案,而不是jquery相关的解决方案,因为我只对一些插件使用jQuery,并管理angularjs中的所有控制器逻辑。另外,jQuery是如何识别angularjs ajax帖子的?在这种情况下,我假设我应该保留一个
count
$scope变量,并在每个ajax帖子/响应上递增/递减它。这是正确的吗?是的,在每次ajax调用返回时递增的范围中应该有一个“count”变量(如示例中所示)。您可以将此方法和Chandermani建议的方法混合使用,一旦所有承诺完成,您就可以使用一个布尔标志,ngClass可以根据需要添加或删除类。我喜欢这个答案,因为它是控制器独立的,因此可以在其他控制器中重用,这就是我的情况。感谢您,我必须在declareDone()或registerNewTask()上使用$scope.$apply()来更新我的视图吗?在我的项目中一直处于这种情况,我想您通常不必这样做,因为触发
registerNewTask()
declareDone()
的事件已经是角度循环的一部分(例如:点击一个按钮,然后是HTTP响应)。我非常喜欢这个进度条,但我不知道它会对多个并发的ajax帖子做出什么反应。它会等待最后一个帖子完成,还是在每次新的Nactrent ajax调用时重新启动?(无论如何,我会尝试一下)另一个问题,既然$q是ES6实现,这是否意味着它只在支持ES6的浏览器上受支持?我至少可以在IE8上运行它吗?我需要额外的插件(Ej.jQuery)来模拟所需的ES6功能吗?我接受@Valentin Waeselynck的答案,因为它可以在多个控制器中重用(这就是我的情况)因为我不能确定Chandermani使用承诺的答案是否能像IE8+这样的浏览器运行(这也是我的例子)。尽管如此,我认为Chandermani关于承诺的答案是现代浏览器的最佳方法。加载条也是很酷的。