詳解為Angular.js內(nèi)置$http服務(wù)添加攔截器的方法
前言
在Angular框架中,創(chuàng)建團(tuán)隊(duì)為使用者進(jìn)行了Ajax請(qǐng)求的封裝,并通過$http服務(wù)暴露出相關(guān)的接口.Angular在其官方文檔中指出, $http服務(wù)底層針對(duì)Web常見的安全攻擊做出了相應(yīng)的對(duì)策,也就是說使用$http服務(wù)封裝的Ajax為使用者提供了更為安全的保障.作為一個(gè)框架,保證框架的可用性,適配性是很有必要的. Angular在設(shè)計(jì),實(shí)現(xiàn)中也體現(xiàn)出來了這樣的良好風(fēng)格.我們通常在使用Ajax時(shí),有時(shí)候希望我們能夠在請(qǐng)求發(fā)起前或接收到請(qǐng)求后做一些相應(yīng)的處理工作,比如:在請(qǐng)求發(fā)起前,在請(qǐng)求頭中添加一下報(bào)文段.在請(qǐng)求返回時(shí)對(duì)一請(qǐng)求處理狀態(tài)做一些管理,如統(tǒng)一處理404狀態(tài)等等.Angular的$http服務(wù)在設(shè)計(jì)實(shí)現(xiàn)時(shí)充分考慮到了上述的情況.接下來,我們一起來學(xué)習(xí)和了解一下如何為$http服務(wù)添加攔截器,以及如何在我們自己實(shí)現(xiàn)的服務(wù)中實(shí)現(xiàn)類似的攔截器機(jī)制.
什么是攔截器–What are Interceptors?
Interceptor(攔截器)在服務(wù)端框架中屬于一種比較常見的機(jī)制,如spring,Struts2等Java框架中攔截器屬于基本配置項(xiàng).攔截器提供了一種機(jī)制可以使開發(fā)者可以定義在一個(gè)action(動(dòng)作)執(zhí)行的前后執(zhí)行的代碼,這些代碼可以是在一個(gè)action執(zhí)行前阻止其執(zhí)行的代碼,也可以是修改目標(biāo)動(dòng)作某些行為的代碼.(在AOP(Aspect-Oriented Programming)中攔截器用于在某個(gè)方法或字段被訪問之前,進(jìn)行攔截然后在之前或之后加入某些操作。在Spring框架中比較常見)
$http服務(wù)中的攔截器
查看API或是源碼我們可以發(fā)現(xiàn),Angular的實(shí)現(xiàn)中通過 httpProvider提供了一個(gè)名為interceptors的數(shù)組.這個(gè)數(shù)組接受攔截器服務(wù)注冊(cè),通過過程次的注冊(cè)最終會(huì)形成攔截器鏈.這樣每次在調(diào)用http服務(wù)的時(shí)候,angular都會(huì)通過我們定義的攔截點(diǎn)(切面)進(jìn)行相應(yīng)的Ajax動(dòng)作修改.理論就不多說了,下面開始進(jìn)入實(shí)戰(zhàn):
Angular中如何聲明一個(gè)攔截器
// Interceptor declaration module.factory('httpInterceptor', ['$log', function($log) { $log.debug('$log is here to show you that this is a regular factory with injection'); return { // do something }; }]);
如何將聲明的攔截器注冊(cè)到$http服務(wù)中
// Add the interceptor to $httpProvider.interceptors module.config(['$httpProvider', function($httpProvider) { $httpProvider.interceptors.push('httpInterceptor'); }]);
通過上面的簡單兩個(gè)步驟,我們基本就完成了http服務(wù)的攔截器編寫與添加.但是上面的代碼片段并不能實(shí)際使用,要想真正的實(shí)現(xiàn)攔截操作,我們還需要遵循h(huán)ttp服務(wù)暴露出來的可以進(jìn)行攔截的點(diǎn)進(jìn)行相關(guān)的代碼編寫.
$httpProvider暴露了那些可以攔截的點(diǎn)?
- request : request方法可以實(shí)現(xiàn)攔截請(qǐng)求: 該方法會(huì)在 http發(fā)送請(qǐng)求到服務(wù)器之前執(zhí)行,因此我們可以在該方法的視線中修改配置或做其他的操作。該方法接收請(qǐng)求配置對(duì)象(requestconfigurationobject)作為參數(shù),然后必須返回配置對(duì)象或者promise。如果返回?zé)o效的配置對(duì)象或者promise則會(huì)被拒絕,導(dǎo)致http 調(diào)用失敗。
- response : response方法可以實(shí)現(xiàn)攔截響應(yīng): 該方法會(huì)在 http接收到從服務(wù)器過來的響應(yīng)之后執(zhí)行,因此我們可以修改響應(yīng)報(bào)文或做其他操作。該方法接收響應(yīng)對(duì)象(responseobject)作為參數(shù),然后必須返回響應(yīng)對(duì)象或者promise。響應(yīng)對(duì)象包括了請(qǐng)求配置(requestconfiguration),頭(headers),狀態(tài)(status)和從后臺(tái)過來的數(shù)據(jù)(data)。如果返回?zé)o效的響應(yīng)對(duì)象或者promise會(huì)被拒絕,導(dǎo)致http 調(diào)用失敗。
- requestError : requestError方法可以實(shí)現(xiàn)攔截請(qǐng)求異常: 有時(shí)候一個(gè)請(qǐng)求發(fā)送失敗或者被攔截器拒絕了。請(qǐng)求異常攔截器會(huì)俘獲那些被上一個(gè)請(qǐng)求攔截器中斷的請(qǐng)求。它可以用來恢復(fù)請(qǐng)求或者有時(shí)可以用來撤銷請(qǐng)求之前所做的配置,比如說關(guān)閉進(jìn)度條,激活按鈕和輸入框什么之類的。
- responseError : responseError方法可以實(shí)現(xiàn)攔截響應(yīng)異常: 有時(shí)候我們后臺(tái)調(diào)用失敗了。也有可能它被一個(gè)請(qǐng)求攔截器拒絕了,或者被上一個(gè)響應(yīng)攔截器中斷了。在這種情況下,響應(yīng)異常攔截器可以幫助我們恢復(fù)后臺(tái)調(diào)用。
對(duì)于上面暴露出來的接口使用也是異常的簡單的,我們可以像聲明一個(gè)簡單的服務(wù)一樣聲明一個(gè)$http服務(wù)的攔截器,并交由angular的注入機(jī)制去使用我們配置的攔截器.
// 如同聲明一個(gè)Angular服務(wù)一樣聲明一個(gè)攔截器 module.factory('sessionInjector', ['authService', function (authService){ return { request: function (config){ if (!authService.isAnonymus) { config.headers['x-session-token'] = authService.token; } return config; } }; }]); // 然后將我們聲明的攔截器添加到$httpProvider的攔截器鏈中,之后的服務(wù)注入Angular會(huì)負(fù)責(zé)幫我們完善 module.config(['$httpProvider', function ($httpProvider){ $httpProvider.interceptors.push('sessionInjector'); }]);
$http服務(wù)攔截器的異步支持
部分場(chǎng)景下,我們希望在攔截器中能夠執(zhí)行一些異步操作.然后依據(jù)不同的處理結(jié)果進(jìn)行不同的攔截操作,AngularJS在設(shè)計(jì)的時(shí)候也很好的支持了這一特性.AngularJS允許我們?cè)跀r截的方法中,我們可以返回一個(gè)promise對(duì)象.如在http服務(wù)中,我們?nèi)绻祷匾粋€(gè)promise對(duì)象時(shí),http服務(wù)將會(huì)延遲發(fā)起網(wǎng)絡(luò)請(qǐng)求或是延遲響應(yīng)請(qǐng)求結(jié)果.
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; }, response: function(response) { var deferred = $q.defer(); someAsyncService.doAsyncOperation().then(function() { // Asynchronous operation succeeded, modify response accordingly ... deferred.resolve(response); }, function() { // Asynchronous operation failed, modify response accordingly ... deferred.resolve(response); }); return deferred.promise; } }; return requestInterceptor; }]);
上面的例子中,在請(qǐng)求發(fā)起時(shí),如果對(duì)應(yīng)的deferred被拒絕,http請(qǐng)求則會(huì)失敗(如果進(jìn)行抓包分析的話,你會(huì)發(fā)現(xiàn)http請(qǐng)求并沒有發(fā)起).在請(qǐng)求進(jìn)行響應(yīng)時(shí),如果deferred被拒絕,則請(qǐng)求也會(huì)失敗.(抓包分析,網(wǎng)絡(luò)請(qǐng)求是有返回的).
總結(jié)
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來一定的幫助,如果有疑問大家可以留言交流。
相關(guān)文章
Angular5給組件本身的標(biāo)簽添加樣式class的方法
本篇文章主要介紹了Angular 5 給組件本身的標(biāo)簽添加樣式class的方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-04-04AngularJs返回前一頁面時(shí)刷新一次前面頁面的方法
今天小編就為大家分享一篇AngularJs返回前一頁面時(shí)刷新一次前面頁面的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2018-10-10AngularJS學(xué)習(xí)第二篇 AngularJS依賴注入
這篇文章主要為大家詳細(xì)介紹了AngularJS學(xué)習(xí)第二篇,理解什么是AngularJS依賴注入,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-02-02Angular外部使用js調(diào)用Angular控制器中的函數(shù)方法或變量用法示例
這篇文章主要介紹了Angular外部使用js調(diào)用Angular控制器中的函數(shù)方法或變量用法,結(jié)合實(shí)例形式分析了Angular基于外部JS調(diào)用控制器中方法與變量的具體實(shí)現(xiàn)步驟與相關(guān)技巧,需要的朋友可以參考下2016-08-08