AngularJS:仅在经过一段时间后才在ajax请求上显示加载微调器

时间:2016-01-08 14:30:09

标签: javascript angularjs ajax angularjs-directive

在我的Angular应用程序中,我实现了this directive(下面的代码),基本上允许我在Angular检测到ajax请求时显示我选择的元素。

但是,为了稍好的可用性,我想在请求开始后经过一段时间(比如100或200毫秒)后才显示微调器,以避免在每个请求上显示那些不必要的分秒显示

实施这样的事情最好的方法是什么?我无法让setTimeoutif块内很好地播放,因为即使我不再有待处理请求,该元素也不会再次被隐藏。

.directive('loading',   ['$http' ,function ($http)
{
    return {
        restrict: 'A',
        link: function (scope, elm, attrs)
        {
            scope.isLoading = function () {
                return $http.pendingRequests.length > 0;
            };

            scope.$watch(scope.isLoading, function (v)
            {
                if(v){
                    elm.show();
                } else {
                    elm.hide();
                }
            });
        }
    };
}]);

2 个答案:

答案 0 :(得分:2)

对于单个全局可用的加载指示器,http拦截器可能是更好的策略。但是假设您想要将它分别附加到单个元素,请尝试以下方法:

.directive('loading', ['$http', '$timeout', function($http, $timeout) {
    return {
        restrict: 'A',
        link: function(scope, elm, attrs) {
            scope.isLoading = function() {
                return $http.pendingRequests.length > 0;
            };

            if (scope.isLoading) {
                elm.hide(); // hide the loading indicator to begin with
                // wait 300ms before setting the watcher:
                $timeout(function() {
                    var watcher = scope.$watch(scope.isLoading, function(v) {
                        if (v) {
                            elm.show();
                        } else {
                            elm.hide();
                            watcher(); // don't forget to clear $watches when you don't need them anymore!
                        }
                    });
                }, 300);
            } else {
                // No pending requests on link; hide the element and stop
                elm.hide();

            }
        }
    };
}]);

(你可能还应该在指令中包含$destroy块来调用watcher(),以防指令超出范围而http请求仍处于未决状态。)

答案 1 :(得分:2)

听起来您可以利用拦截器并绑定到根变量而不是指令来显示您的元素以查找待处理的ajax请求(在满足时间阈值之后)。观察以下可能性......

app.factory('HttpInterceptor', ['$rootScope', '$q', '$timeout', function ($rootScope, $q, $timeout) {

    return {
        'request': function (config) {

            $timeout(function() {
                $rootScope.isLoading = true;    // loading after 200ms
            }, 200);

            return config || $q.when(config);   
        },
        'requestError': function (rejection) {
            /*...*/
            return $q.reject(rejection);
        },
        'response': function (response) {       

            $rootScope.isLoading = false;       // done loading

            return response || $q.when(response);
        },
        'responseError': function (rejection) {
            /*...*/
            return $q.reject(rejection);
        }
    };
}]);
// register interceptor
app.config(['$httpProvider', function ($httpProvider) {
    $httpProvider.interceptors.push('HttpInterceptor');
    /*...*/
}]);
<!-- plain element with binding -->
<div class="whatever" ng-show="isLoading"></div>

JSFiddle Link - 工作演示