web-dev-qa-db-fra.com

Angular js - détecte quand tout $ http () a fini

Ok j'ai des tonnes d'appels $http() tout autour du code de l'application,

je me demande s’il existe un moyen/meilleure pratique de détecter quand tous les $http() de l’application sont terminés (succès/erreur ne tient pas compte de ce qu’ils retournent, il suffit de savoir si l’opération est terminée)?

Pour que je puisse montrer un gif de chargement jusqu'au chargement?

merci

24
itsme

Fais-le comme ça:

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');
}]);

Puis utilisez l'événement lié à $rootScope n'importe où (préférable d'utiliser la directive):

$rootScope.$on('loading:progress', function (){
    // show loading gif
});

$rootScope.$on('loading:finish', function (){
    // hide loading gif
});
51
karaxuna

C'est possible si vous exécutez toutes les requêtes par $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]
});

En utilisant ng-if, vous pouvez afficher et masquer le chargement gif

Si vous utilisez un appel $http différent, indiquez count ou array dans le $rootScope et mettez-le à jour à la fin du $http. Sur la base de count ou array.length, activez le chargement gif.

10
Fizer Khan

En utilisant answer by @karaxuna, j’implémente ma solution comme ci-dessous . 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
Frank Myat Thu