$http服務容許咱們使用http請求和後臺作通訊,可是在每一次放鬆請求以前咱們都但願可以捕捉這個請求而且進行操做,好比以前富瑞中每個請求中header要放入用戶名和密碼同樣,富瑞的作法是放了一個全局變量,可是這個方法是很是不可取的!所有變量污染的問題,因此在angularjs指令中的攔截器就是個很好的解決方案!而後對於http請求的一些服務也能夠有一個很好的統一的處理方法git
下面具體說下$httpprovider中的interceptors,下面稱之爲攔截器
其實也就是$httpprovider服務包含一個攔截器數組,是一個簡單的factory註冊進來的。angularjs
建立攔截器:
寫一個factorygithub
angular.module('pldApp.services', []) .factory('authInterceptor',function () { return { request: function (config) { config.headers = config.headers || {}; var token = JSON.parse(window.localStorage.getItem("token")) || ""; config.headers.Authorization = 'Bearer ' + token.access_token; return config; } }; });
config裏面配置json
$httpProvider.interceptors.push('authInterceptor');
而後在每一次發送請求的時候都調用request方法,這裏我打印了config的具體信息,其實這裏你們能夠看到請求的具體內容,而後咱們能夠在他發送請求以前大肆的改動請求的內容。api
這裏我用的是request方法
攔截器容許有一下四個操做:
一、 請求的攔截:request
這個方法的調用在$http請求以前
因此在此以前咱們能夠修改配置和進行其餘操做!
二、 攔截響應:response
當$http服務收到後臺給出響應的時候,這個方法被調用。因此咱們能夠修改請求響應。這個方法接受一個響應對象做爲參數。響應對象包含請求配置、標題、狀態以及從後臺返回的數據。若是返回的是一個無效的對象或者是promise,這個是不會調用的。
三、 攔截請求錯誤:requestError
四、 攔截響應錯誤:responseError
這裏注意攔截響應錯誤!!!當你的controller這麼寫的時候數組
$scope.getLogin = function(){ $scope.myLoading(); loginService.getLogin($scope.user.name,$scope.user.paw).success(function(data){ window.localStorage.setItem("token",JSON.stringify(data)); window.localStorage.setItem("username",$scope.user.name); window.localStorage.setItem("password",$scope.user.paw); //獲取用戶信息 loginService.getUserInfo().success(function(data){ mineService.setInifo(data); }).error(function(status,error){ $ionicLoading.show({ template:chargeStatus(status) }); }); $scope.lodingHide(); $scope.skipPage('tab.homePage'); }).error(function(error,status){ $ionicLoading.show({ template:chargeStatus(status) }); $timeout(function () { $ionicLoading.hide(); },2000); }); };
若是登陸名和密碼錯誤了,可是你依舊這麼封裝responseError的話,controller會執行成功毀掉函數的promise
因此這裏咱們其實須要本身從新封裝個promise的,這樣纔可以讓controller中執行失敗的回調函數。session
因此上面三個個人寫法是這樣的app
angular.module('pldApp.services', []) .factory('authInterceptor',function ($q) { return { request: function (config) { config.headers = config.headers || {}; var token = JSON.parse(window.localStorage.getItem("token")) || ""; config.headers.Authorization = 'Bearer ' + token.access_token; return config; }, response: function(response) { console.log("response:"); console.log(response); return response; }, responseError:function(errorReason){ console.log(errorReason); return $q.reject(errorReason); }, requestError:function(errorReason){ console.log(2); return $q.reject(errorReason); } }; });
由於這個我也接觸的不是特別深刻,因此這裏給你們只是簡單的介紹了下基本用法異步
下面是從網上找的一些引用:
異步操做:
module.factory('myInterceptor', ['$q', 'someAsyncService', function($q, someAsyncService) { var requestInterceptor = { request: function(config) { var deferred = $q.defer(); someAsyncService.doAsyncOperation().then(function() { // Asynchronous operation succeeded, modify config accordingly ... deferred.resolve(config); }, function() { // Asynchronous operation failed, modify config accordingly ... deferred.resolve(config); }); return deferred.promise; } }; return requestInterceptor; }]);
Session 攔截器
如今建立一個get請求:
$http.get('https://api.github.com/users/naorye/repos');
被以前的配置對象 sessionInjector :
{ "transformRequest": [ null ], "transformResponse": [ null ], "method": "GET", "url": "https://api.github.com/users/naorye/repos", "headers": { "Accept": "application/json, text/plain, */*" } }
配置對象 sessionInjector :
{ "transformRequest": [ null ], "transformResponse": [ null ], "method": "GET", "url": "https://api.github.com/users/naorye/repos", "headers": { "Accept": "application/json, text/plain, */*", "x-session-token": 415954427904 } }
請求恢復攔截器:
module.factory('requestRejector', ['$q', function($q) { var requestRejector = { request: function(config) { return $q.reject('requestRejector'); } }; return requestRejector; }]); module.factory('requestRecoverer', ['$q', function($q) { var requestRecoverer = { requestError: function(rejectReason) { if (rejectReason === 'requestRejector') { // Recover the request return { transformRequest: [], transformResponse: [], method: 'GET', url: 'https://api.github.com/users/naorye/repos', headers: { Accept: 'application/json, text/plain, */*' } }; } else { return $q.reject(rejectReason); } } }; return requestRecoverer; }]); module.config(['$httpProvider', function($httpProvider) { $httpProvider.interceptors.push('requestRejector'); // Removing 'requestRecoverer' will result to failed request $httpProvider.interceptors.push('requestRecoverer'); }]);
Session recover攔截器的使用
module.factory('sessionRecoverer', ['$q', '$injector', function($q, $injector) { var sessionRecoverer = { responseError: function(response) { // Session has expired if (response.status == 419){ var SessionService = $injector.get('SessionService'); var $http = $injector.get('$http'); var deferred = $q.defer(); // Create a new session (recover the session) // We use login method that logs the user in using the current credentials and // returns a promise SessionService.login().then(deferred.resolve, deferred.reject); // When the session recovered, make the same backend call again and chain the request return deferred.promise.then(function() { return $http(response.config); }); } return $q.reject(response); } }; return sessionRecoverer; }]); module.config(['$httpProvider', function($httpProvider) { $httpProvider.interceptors.push('sessionRecoverer'); }]);
這裏就是說道了,要從新封裝promise。
這一塊其實我也只是剛剛踏入瞭解,若是後續你們有研究,能夠互相討論討論!說到這,是否是發現$q頗有搞頭?!有必要研究下?!