AngualrJS中每次$http请求时的一个遮罩层Directive

 

在AngualrJS中使用$http每次向远程API发送请求,等待响应,这中间有些许的等待过程。如何优雅地处理这个等待过程呢?

如果我们在等待过程中弹出一个遮罩层,会是一个比较优雅的做法。

这就涉及到了对$http的请求响应进行拦截了。请求的时候,弹出一个遮罩层,收到响应的时候把遮罩层隐藏。

其实,$httpProvider已经为我们提供了一个$httpProvider.interceptors属性,我们只需要把自定义的拦截器放到该集合中就可以了。

如何表现呢?大致是这样的:

 

<div data-my-overlay>
    <br/><img src="spinner.gif" /> &nbsp;&nbsp;Loading
</div>

 

显示加载的图片被包含在Directive中了,肯定会用到transclusion。

还涉及到一个遮罩层弹出延迟时间的问题,这个我们希望在config中通过API设置,所以,我们有必要创建一个provider,通过这个设置延迟时间。

$http请求响应遮罩层的Directive:

 

(function(){
    var myOverlayDirective =function($q, $timeout, $window, httpInterceptor, myOverlayConfig){
        return {
            restrict: 'EA',
            transclude: true,
            scope: {
                myOverlayDelay: "@"
            },
            template: '<div id="overlay-container" class="onverlayContainer">' +
                            '<div id="overlay-background" class="onverlayBackground"></div>' +
                            '<div id="onverlay-content" class="onverlayContent" data-ng-transclude>' +
                            '</div>' +
                        '</div>',
            link: function(scope, element, attrs){
                var overlayContainer = null,
                    timePromise = null,
                    timerPromiseHide = null,
                    inSession = false,
                    queue = [],
                    overlayConfig = myOverlayConfig.getConfig();
                    
                init();
                
                //初始化
                function init(){
                    wireUpHttpInterceptor();
                    if(window.jQuery) wirejQueryInterceptor();
                    overlayContainer = document.getElementById('overlay-container');
                }
                
                //自定义Angular的http拦截器
                function wireUpHttpInterceptor(){
                
                    //请求拦截
                    httpInterceptor.request = function(config){
                        //判断是否满足显示遮罩的条件
                        if(shouldShowOverlay(config.method, config.url)){
                            processRequest();
                        }
                        return config || $q.when(config);
                    };
                    
                    //响应拦截
                    httpInterceptor.response = function(response){
                        processResponse();
                        return response || $q.when(response);
                    }
                    
                    //异常拦截
                    httpInterceptor.responseError = function(rejection){
                        processResponse();
                        return $q.reject(rejection);
                    }
                }
                
                //自定义jQuery的http拦截器
                function wirejQueryInterceptor(){
                
                    $(document).ajaxStart(function(){
                        processRequest();
                    });
                    
                    $(document).ajaxComplete(function(){
                        processResponse();
                    });
                    
                    $(document).ajaxError(function(){
                        processResponse();
                    });
                }
                
                //处理请求
                function processRequest(){
                    queue.push({});
                    if(queue.length == 1){
                        timePromise = $timeout(function(){
                            if(queue.length) showOverlay();
                        }, scope.myOverlayDelay ? scope.myOverlayDelay : overlayConfig.delay);
                    }
                }
                
                //处理响应
                function processResponse(){
                    queue.pop();
                    if(queue.length == 0){
                        timerPromiseHide = $timeout(function(){
                            hideOverlay();
                            if(timerPromiseHide) $timeout.cancel(timerPromiseHide);
                        },scope.myOverlayDelay ? scope.myOverlayDelay : overlayConfig.delay);
                    }
                }
                
                //显示遮罩层
                function showOverlay(){
                    var w = 0;
                    var h = 0;
                    if(!$window.innerWidth){
                        if(!(document.documentElement.clientWidth == 0)){
                            w = document.documentElement.clientWidth;
                            h = document.documentElement.clientHeight;
                        } else {
                            w = document.body.clientWidth;
                            h = document.body. clientHeight;
                        }
                    }else{
                        w = $window.innerWidth;
                        h = $window.innerHeight;
                    }
                    var content = docuemnt.getElementById('overlay-content');
                    var contetWidth = parseInt(getComputedStyle(content, 'width').replace('px',''));
                    var contentHeight = parseInt(getComputedStyle(content, 'height').replace('px',''));
                    
                    content.style.top = h / 2 - contentHeight / 2 + 'px';
                    content.style.left = w / 2 - contentWidth / 2 + 'px';
                    
                    overlayContainer.style.display = 'block';
                }
                
                function hideOverlay(){
                    if(timePromise) $timeout.cancel(timerPromise);
                    overlayContainer.style.display = 'none';
                }
                
                //得到一个函数的执行结果
                var getComputedStyle = function(){
                
                    var func = null;
                    
                    if(document.defaultView && document.defaultView.getComputedStyle){
                        func = document.defaultView.getComputedStyle;
                    } else if(typeof(document.body.currentStyle) !== "undefined"){
                        func = function(element, anything){
                            return element["currentStyle"];
                        }
                    }
                    
                    return function(element, style){
                        reutrn func(element, null)[style];
                    }
                }();
                
                //决定是否显示遮罩层
                function shouldShowOverlay(method, url){
                    var searchCriteria = {
                        method: method,
                        url: url
                    };
                    
                    return angular.isUndefined(findUrl(overlayConfig.exceptUrls, searchCriteria));
                }
                
                function findUrl(urlList, searchCriteria){
                    var retVal = undefined;
                    angular.forEach(urlList, function(url){
                        if(angular.equals(url, searchCriteria)){
                            retVal = true;
                            return false;//推出循环
                        }
                    })
                    return retVal;
                }
            }
        }
    };

    //配置$httpProvider
    var httpProvider = function($httpProvider){
        $httpProvider.interceptors.push('httpInterceptor');
    };
    
    //自定义interceptor
    var httpInterceptor = function(){
      return  {};
    };
    
    
    //提供配置
    var myOverlayConfig = function(){
        //默认配置
        var config = {
            delay: 500,
            exceptUrl: []
        };
        
        //设置延迟
        this.setDelay = function(delayTime){
            config.delay = delayTime;
        }
        
        //设置异常处理url
        this.setExceptionUrl = function(urlList){
            config.exceptUrl = urlList;
        };
        
        //获取配置
        this.$get = function(){
            return {
                getDelayTime: getDelayTime, 
                getExceptUrls: getExceptUrls,
                getConfig: getConfig
            }
            
            function getDelayTime(){
                return config.delay;
            }
            
            function getExeptUrls(){
                return config.exceptUrls;
            }
            
            function getConfig(){
                return config;
            }
        };
    };
    
    
    var myDirectiveApp = angular.module('my.Directive',[]);
    myDirectiveApp.provider('myOverlayConfig', myOverlayConfig);
    myDirectiveApp.factory('httpInterceptor', httpInterceptor);
    myDirectiveApp.config('$httpProvider', httpProvider);
    myDirectiveApp.directive('myOverlay', ['$q', '$timeout', '$window', 'httpInceptor', 'myOverlayConfig', myOverlayDirective]);
}());

 

在全局配置中:

 

(functioin(){
    angular.module('customersApp',['ngRoute', 'my.Directive'])
        .config(['$routeProvider, 'myOverlayConfigProvider', funciton($routeProvider, myOverlayConfigProvider){
                ...
                myOverlayConfigProvider.setDealy(100);
                myOverlayConfigProvider.setExceptionUrl({
                    method: 'GET',
                    url: ''
                });
        }]);
}());

 

你可能感兴趣的:(AngualrJS中每次$http请求时的一个遮罩层Directive)