AngularJS est un framework MVC frontal très puissant. Utilisez $http dans AngualrJS pour envoyer une requête à l'API distante à chaque fois et attendez la réponse. Il y a un léger processus d'attente entre les deux. Comment gérer ce processus d’attente avec élégance ?
Ce serait une approche plus élégante si nous affichons un calque de masque en attendant.
Cela implique d'intercepter les réponses aux requêtes $http. Lors de la demande, un calque de masque apparaît et lorsque la réponse est reçue, le calque de masque est masqué.
En fait, $httpProvider nous a déjà fourni une propriété $httpProvider.interceptors, et il nous suffit de mettre les intercepteurs personnalisés dans cette collection.
Comment se comporter ? C'est à peu près comme ça :
<div data-my-overlay> <br/><img src="spinner.gif" /> Loading </div>
Montrez que l'image chargée est incluse dans la directive et que la transclusion sera certainement utilisée.
Cela implique également le problème du temps de retard des pop-ups de la couche de masque. Nous espérons régler cela via l'API dans la configuration, il est donc nécessaire pour nous de créer un fournisseur et de définir le temps de retard via celui-ci.
$http directive de couche de masque de réponse à la demande :
(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]); }());
En configuration globale :
(functioin(){ angular.module('customersApp',['ngRoute', 'my.Directive']) .config(['$routeProvider, 'myOverlayConfigProvider', funciton($routeProvider, myOverlayConfigProvider){ ... myOverlayConfigProvider.setDealy(100); myOverlayConfigProvider.setExceptionUrl({ method: 'GET', url: '' }); }]); }());
Ce qui précède est une directive de calque de masque pour chaque requête $http dans AngualrJS que l'éditeur a partagée avec vous. J'espère qu'elle sera utile à tout le monde.