Angular js - detect when all $http() have finished

后端 未结 3 1431
一生所求
一生所求 2020-12-12 19:47

Ok i have tons of $http() calls all around the app code,

i\'m wondering is there any way / best practice to detect when all $http() around

相关标签:
3条回答
  • 2020-12-12 20:01

    Do it like this:

    angular.module('app').factory('httpInterceptor', ['$q', '$rootScope',
        function ($q, $rootScope) {
            var loadingCount = 0;
    
            return {
                request: function (config) {
                    if(++loadingCount === 1) $rootScope.$broadcast('loading:progress');
                    return config || $q.when(config);
                },
    
                response: function (response) {
                    if(--loadingCount === 0) $rootScope.$broadcast('loading:finish');
                    return response || $q.when(response);
                },
    
                responseError: function (response) {
                    if(--loadingCount === 0) $rootScope.$broadcast('loading:finish');
                    return $q.reject(response);
                }
            };
        }
    ]).config(['$httpProvider', function ($httpProvider) {
        $httpProvider.interceptors.push('httpInterceptor');
    }]);
    

    Then use event bound to $rootScope anywhere (preferable to use in directive):

    $rootScope.$on('loading:progress', function (){
        // show loading gif
    });
    
    $rootScope.$on('loading:finish', function (){
        // hide loading gif
    });
    
    0 讨论(0)
  • 2020-12-12 20:01

    Using answer by @karaxuna, I implement my solution like below. Plunker

    <!doctype html>
    <html ng-app="ui.bootstrap.demo">
      <head>
        <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.7/angular.js"></script>
        <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.7/angular-animate.js"></script>
        <script src="https://angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.14.3.js"></script>
        <script>
        var app = angular.module('ui.bootstrap.demo', ['ngAnimate', 'ui.bootstrap']);
    
        app.config(['$httpProvider', function ($httpProvider) {
            $httpProvider.interceptors.push(function ($q, $rootScope, $templateCache) {
                var AjaxLoadingCount = 0;
                return {
                    request: function (config) {
                        console.log("[config.interceptorService] request config", config);                  
                        if (++AjaxLoadingCount === 1)
                        {
                            if (!$templateCache.get(config.url)) {
                                $rootScope.$broadcast('AjaxLoading:Progress');
                            }
                        }
                        return config || $q.when(config);
                    },
                    requestError: function (rejection) {
                        console.log("[config.interceptorService] requestError rejection", rejection);
                        if(--AjaxLoadingCount === 0) $rootScope.$broadcast('AjaxLoading:Finish');
                        return $q.reject(rejection);
                    },
                    response: function (response) {
                        console.log("[config.interceptorService] response response", response); 
                        if(--AjaxLoadingCount === 0) $rootScope.$broadcast('AjaxLoading:Finish');
                        return response || $q.when(response);                   
                    },
                    responseError: function (rejection) {
                        console.log("[config.interceptorService] responseError rejection", rejection);
                        if(--AjaxLoadingCount === 0) $rootScope.$broadcast('AjaxLoading:Finish');
                        return $q.reject(rejection);
                    }
                };
            });
        }]);
    
        app.factory('ajaxFactory', function ($http) {
    
            var ajaxFactory = {};
            ajaxFactory.LoadData = function () {            
                return $http({
                    method: "GET",
                    url: "http://www.w3schools.com/angular/customers.php",
                });
            };
            return ajaxFactory;
    
        });
    
        app.controller('ModalDemoCtrl', function ($scope, ajaxFactory) {
            $scope.doAjax = function () {
    
                ajaxFactory.LoadData()
                .success(function (data, status, headers, config) {
                    console.log("Data vai factory\n", JSON.stringify(data));
                    console.log("Loading finish.");             
                }).error(function (data, status, headers, config) {
    
                });
            };
        });
    
        app.directive("ajaxLoadingDirective", function ($uibModal) {
            var modalInstance;
            return {
                restrict: 'EA', //E = element, A = attribute, C = class, M = comment            
                scope: true,
                link: function (scope, elem, attrs) {
                    console.log("AjaxLoadingDirective.AjaxLoading:Progress");
                    scope.$on("AjaxLoading:Progress", function () {                 
                        modalInstance = $uibModal.open({
                            animation: true,
                            templateUrl: 'myModalContent.html'
                        });
                    });
                    return scope.$on("AjaxLoading:Finish", function () {
                        console.log("AjaxLoadingDirective.AjaxLoading:Finish");
                        if(modalInstance === undefined) return;
                        modalInstance.dismiss();
                    });
                }
            }
        });
    
        </script>
        <link href="https://netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet">
      </head>
      <body>
        <div ng-controller="ModalDemoCtrl">
            <script type="text/ng-template" id="myModalContent.html">
                Loading data .......................            
            </script>
            <button type="button" class="btn btn-default" ng-click="doAjax()">Execute Ajax</button>
            <div ajax-loading-directive ></div>
        </div>
      </body>
    </html>
    
    0 讨论(0)
  • 2020-12-12 20:07

    It is possible if you execute all requests by $q.all

    $scope.request1 = $http.get('request1URL', {cache: false});
    $scope.request2 = $http.get('request2URL', {'cache': false});
    $scope.loading = true;
    
    $q.all([$scope.request1, $scope.request2]).then(function(values) {
         $scope.loading = false;
         // Do whatever you want
         // values[0], values[1]
    });
    

    Using ng-if, you can show and hide loading gif.

    In case, if you use different $http call, then have a count or array in the $rootScope and update them whenever $http complete. Based on the count or array.length enable the loading gif.

    0 讨论(0)
提交回复
热议问题