AngularJS中的http攔截

Darren Ji發表於2016-02-08

 

$http服務允許我們與服務端互動,有時候我們希望在發出請求之前以及收到響應之後做些事情。即http攔截。

$httpProvider包含了一個interceptors的陣列。

我們這樣建立一個interceptor。

 

app.factory('myInterceptor', ['$log', function($log){
    $log.debug('');
    
    var myInterceptor = {};
    
    return myInterceptor;
}])

 

接著註冊interceptor.

 

app.config(['$httpProvider', function($httpProvider){
    $httpProvider.interceptors.push('myInterceptor');
}])

 

以下是$http攔截的一些例子。

■ 攔截器中的非同步操作

 

app.factory('myInterceotpr','someAsyncServcie', function($q, someAsyncServcie){
    var requestInterceptor = {
        request: function(config){
            var deferred = %q.defer();
            someAsyncService.doAsyncOperation().then(function(){
                ...
                deferred.resolve(config);
            }, function(){
                ...
                deferred.resolve(config);
            })
            return deferred.promise;
        }
    };
    
    return requestInterceptor;
})

以上,是一個請求攔截,做了一個非同步操作,根據非同步操作的結果來更新config。

當然也有響應攔截。

 

app.factory('myInterceptor',['$q', 'someAsyncService', function($q, someAsyncSercice){
    var responseInterceptor = {
        response: function(response){
            var deferred = $q.defer();
            someAsyncService.doAsyncOperation().then(function(response){
                ...
                deferred.resolve(response);
            }, function(response){
                ...
                deferred.resolve(response);
            })
            return deferred.promise;
        }
    };
    return responseInterceptor;
}])

 

■ Session攔截,請求攔截

服務端有2種型別的驗證,一個是基於cookie的,一種是基於token的。對於基於token驗證,當使用者登入,獲取一個來自服務端的token,這個token在每一次請求時傳送給服務端。

建立一個有關session的injector:

app.factory('sessionInjector',['SessionService', function(SessionService){
    var sessionInjector = {
        request: function(config){
            if(!SessionService.isAnonymous){
                config.headers['x-session-token'] = SessionService.token;
            }
            return config;
        }
    };
    
    return sessionInjector;
}])

可見,把從服務端返回的token放在了config.headers中。

註冊injector:

app.config(['$httpProvider', function($httpProvider){
    $httpProvider.interceptors.push('sessionInjector');
}])

發出一個請求:
$http.get('');

攔截前大致是:

{
    "transformRequest":[null],
    "transformResponse":[null],
    "method":"GET",
    "url":"",
    "headers":{
        "Accept": "application/json, text/plain,*/*"
    }
}

攔截後,在headers中多兩個一個x-session-token欄位:

{
    "transformRequest":[null],
    "transformResponse":[null],
    "method":"GET",
    "url":"",
    "headers":{
        "Accept": "application/json, text/plain,*/*",
        "x-session-token":......
    }
}

■ 時間戳,請求和響應攔截

 

app.factory('timestampMarker',[function(){
    var timestampMarker = {
        request:function(config){
            config.requestTimestamp = new Date().getTime();
            return config;
        },
        response: function(response){
            response.config.responseTimestamp = new Date().getTime();
            return config;
        }
    };
    
    return timestampMarker;
}])

以上,在請求和響應時攔截,在config.requestTimestamp和config.responseTimestamp賦上當前的時間。

註冊攔截器:

app.config(['$httpProvider', function($httpProvider){
    $httpProvider.interceptors.push('timestampMarker');
}])

 

然後在運用的時候可以算出請求響應所耗去的時間。

$http.get('').then(function(response){
    var time = response.config.responseTime - response.config.requestTimestamp;
    console.log('請求耗去的時間為 ' + time);
})

 


■ 請求錯誤恢復,請求攔截

模擬一個請求攔截的錯誤情形:

 

app.factory('requestRejector',['$q', function($q){
    var requestRejector = {
        request: function(config){
            return $q.reject('requestRejector');
        }
    };
    return requestRejector;
}])

 

攔截請求錯誤:

app.factory('requestRecoverer',['$q', function($q){
    var requestRecoverer = {
        requestError: function(rejectReason){
            if(rejectReason === 'requestRejector'){
                //恢復請求
                return {
                    transformRequest:[],
                    transformResponse:[],
                    method:'GET',
                    url:'',
                    headers:{
                        Accept:'application/json, text/plain, */*'
                    }
                };
            } else {
                return $q.reject(rejectReason);
            }
        }
    };
    
    return requestRecoverer;
}])

 

註冊攔截器:

app.config(['$httpProvider', function($httpProvider){
    $httpProvider.interceptors.push('requestRejector');
    $httpProvider.interceptors.push('requestRecoverer');
}])

 

■ Session錯誤恢復,響應攔截

 

app.factory('sessionRecoverer',['$q','$injector',function($q, $injector){
    var sessionRecoverer = {
        responseError: function(response){
            //如果Session過期
            if(response.status == 419){
                var SessionService = $injector.get('SessionService');
                var $http = $injector.get('$http');
                var deferred = $q.defer();
                
                //建立一個新的session
                SessionService.login().then(deferred.resolve, deferred.reject);
                
                return deferred.promise.then(function(){
                    reutrn $http(response.config);
                })
            }
            return $q.reject(response);
        }
    };
    
    return sessionRecoverer;
}])

 

參考資料:http://www.webdeveasy.com/

 

相關文章