你的位置:首页 > Java教程

[Java教程]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" >' +              '<div id="overlay-background" ></div>' +              '<div id="onverlay-content" 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: ''        });    }]);}());