AngularJS是一款非常强大的前端MVC框架。在AngualrJS中使用$http每次向远程API发送请求,等待响应,这中间有些许的等待过程。如何优雅地处理这个等待过程呢?
如果我们在等待过程中弹出一个遮罩层,会是一个比较优雅的做法。
这就涉及到了对$http的请求响应进行拦截了。请求的时候,弹出一个遮罩层,收到响应的时候把遮罩层隐藏。
其实,$httpProvider已经为我们提供了一个$httpProvider.interceptors属性,我们只需要把自定义的拦截器放到该集合中就可以了。
如何表现呢?大致是这样的:
<div data-my-overlay> <br/><img src=\"spinner.gif\" /> 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 ,希望对大家有所帮助。
本文地址:https://www.stayed.cn/item/8861
转载请注明出处。
本站部分内容来源于网络,如侵犯到您的权益,请 联系我