AngualrJS中每次$http请求时的一个遮罩层Directive
AngularJS是一款非常强大的前端MVC框架。在AngualrJS中使用$http每次向远程API发送请求,等待响应,这中间有些许的等待过程。如何优雅地处理这个等待过程呢?
如果我们在等待过程中弹出一个遮罩层,会是一个比较优雅的做法。
这就涉及到了对$http的请求响应进行拦截了。请求的时候,弹出一个遮罩层,收到响应的时候把遮罩层隐藏。
其实,$httpProvider已经为我们提供了一个$httpProvider.interceptors属性,我们只需要把自定义的拦截器放到该集合中就可以了。
如何表现呢?大致是这样的:
<divdata-my-overlay> <br/><imgsrc="spinner.gif"/> Loading </div>
显示加载的图片被包含在Directive中了,肯定会用到transclusion。
还涉及到一个遮罩层弹出延迟时间的问题,这个我们希望在config中通过API设置,所以,我们有必要创建一个provider,通过这个设置延迟时间。
$http请求响应遮罩层的Directive:
(function(){ varmyOverlayDirective=function($q,$timeout,$window,httpInterceptor,myOverlayConfig){ return{ restrict:'EA', transclude:true, scope:{ myOverlayDelay:"@" }, template:'<divid="overlay-container"class="onverlayContainer">'+ '<divid="overlay-background"class="onverlayBackground"></div>'+ '<divid="onverlay-content"class="onverlayContent"data-ng-transclude>'+ '</div>'+ '</div>', link:function(scope,element,attrs){ varoverlayContainer=null, timePromise=null, timerPromiseHide=null, inSession=false, queue=[], overlayConfig=myOverlayConfig.getConfig(); init(); //初始化 functioninit(){ wireUpHttpInterceptor(); if(window.jQuery)wirejQueryInterceptor(); overlayContainer=document.getElementById('overlay-container'); } //自定义Angular的http拦截器 functionwireUpHttpInterceptor(){ //请求拦截 httpInterceptor.request=function(config){ //判断是否满足显示遮罩的条件 if(shouldShowOverlay(config.method,config.url)){ processRequest(); } returnconfig||$q.when(config); }; //响应拦截 httpInterceptor.response=function(response){ processResponse(); returnresponse||$q.when(response); } //异常拦截 httpInterceptor.responseError=function(rejection){ processResponse(); return$q.reject(rejection); } } //自定义jQuery的http拦截器 functionwirejQueryInterceptor(){ $(document).ajaxStart(function(){ processRequest(); }); $(document).ajaxComplete(function(){ processResponse(); }); $(document).ajaxError(function(){ processResponse(); }); } //处理请求 functionprocessRequest(){ queue.push({}); if(queue.length==1){ timePromise=$timeout(function(){ if(queue.length)showOverlay(); },scope.myOverlayDelay?scope.myOverlayDelay:overlayConfig.delay); } } //处理响应 functionprocessResponse(){ queue.pop(); if(queue.length==0){ timerPromiseHide=$timeout(function(){ hideOverlay(); if(timerPromiseHide)$timeout.cancel(timerPromiseHide); },scope.myOverlayDelay?scope.myOverlayDelay:overlayConfig.delay); } } //显示遮罩层 functionshowOverlay(){ varw=0; varh=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; } varcontent=docuemnt.getElementById('overlay-content'); varcontetWidth=parseInt(getComputedStyle(content,'width').replace('px','')); varcontentHeight=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'; } functionhideOverlay(){ if(timePromise)$timeout.cancel(timerPromise); overlayContainer.style.display='none'; } //得到一个函数的执行结果 vargetComputedStyle=function(){ varfunc=null; if(document.defaultView&&document.defaultView.getComputedStyle){ func=document.defaultView.getComputedStyle; }elseif(typeof(document.body.currentStyle)!=="undefined"){ func=function(element,anything){ returnelement["currentStyle"]; } } returnfunction(element,style){ reutrnfunc(element,null)[style]; } }(); //决定是否显示遮罩层 functionshouldShowOverlay(method,url){ varsearchCriteria={ method:method, url:url }; returnangular.isUndefined(findUrl(overlayConfig.exceptUrls,searchCriteria)); } functionfindUrl(urlList,searchCriteria){ varretVal=undefined; angular.forEach(urlList,function(url){ if(angular.equals(url,searchCriteria)){ retVal=true; returnfalse;//推出循环 } }) returnretVal; } } } }; //配置$httpProvider varhttpProvider=function($httpProvider){ $httpProvider.interceptors.push('httpInterceptor'); }; //自定义interceptor varhttpInterceptor=function(){ return{}; }; //提供配置 varmyOverlayConfig=function(){ //默认配置 varconfig={ 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 } functiongetDelayTime(){ returnconfig.delay; } functiongetExeptUrls(){ returnconfig.exceptUrls; } functiongetConfig(){ returnconfig; } }; }; varmyDirectiveApp=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,希望对大家有所帮助。