上一篇中分析了axios傳送一個簡單的get請求的完整的流程,傳送門,戳這裡。
這一篇講主要來分析下axios是如何實現攔截器的,這裡只分析請求攔截器。
axios.interceptors.request.use(function(config){
// ...
return config;
}, function(err){
// ...
return Promise.reject(err)
})
複製程式碼
上面的程式碼就是定義一個請求的攔截器,需要注意的是攔截器是要在傳送請求之前定義的!
axios是一個函式我們都知道了,interceptors屬性是什麼時候定義上的呢?上一篇分析了axios上好多屬性都是從context和instance上繼承來的,所以還是按照整個思路分析,來看axios/lib/core/Axios.js
檔案。
function Axios(){
this.interceptors = {
request = new InterceptorManager()
}
}
複製程式碼
context是Axios的例項化物件,有interceptors物件,所以axios繼承來,也是可以訪問的到的,清楚這一點就順勢去axios/lib/core/InterceptorManager.js
檔案中看InterceptorManager這個建構函式吧!
function InterceptorManager(){
this.handlers = [];
}
InterceptorManager.prototype.use = function use(fulfilled, rejected){
this.handlers.push({
fulfilled : fulfilled,
rejected : rejected
});
return this.handler.length - 1;
}
複製程式碼
從上面可以看到,use是定義在建構函式的原型上的,所以它的例項化物件是可以訪問的,所以到現在,axios.interceptors.request.use()我們已經解釋清楚了,就是上面的函式,進入函式看下到底做了什麼,我們定義的完成和失敗的兩個回撥函式被push到一個handlers陣列中去了,那麼這個handlers陣列到底有什麼意義呢?
目前來說好像分析被中斷了,不知道該如和進行下去,但是上一節我們在分析Axios.prototype.request方法的時候省略過一些關於攔截器的東西,去看看axios/lib/core/Axios.js
。
Axios.prototype.request = function(config){
// ...
// 對config進行處理的程式碼還是省略掉
var chain = [dispatchRequest, undefind];
var promise = Promise.resolve(config);
this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor){
// 這是上一節分析省略掉的一個函式
// 關於這個forEach函式就是去遍歷 剛才不知道是什麼用的handlers陣列;
chain.unshift(interceptor.fulfilled, interceptor.rejected);
// 就是把我們定義的攔截器的回撥函式加入到chain的首部
})
// 關於response的也省略掉
// 假設我們只定義了一組攔截器回撥函式,那麼現在chain應該是這樣的
// chain = [fulfilled, rejected, dispatchRequest, undefined];
while(chain.length){
promise = promise.then(chain.shift(), chain.shift())
}
// 經過迴圈這個promise就成了
/**
* promise = promise.resolve(conifg)
* .then(interceptor.fulfilled, interceptor.rejected)
* .then(dispatchRequest, undefined)
*/
return promise
}
複製程式碼
結合上一篇我們知道這個函式返回的promise是我們傳送請求之後的promise,但是在傳送請求之前先執行了fufilled(config)和rejected(err)組成的promise,這個promise執行並且resolve後才會去執行dispatchRequest(config);如果返回了reject那麼請求promise將終止,會被axios.get().catch()捕獲,所以這就是所謂的攔截。
對響應攔截器的處理也同樣是這個道理,只是將interceptor.fulfilled和interceptor.rejected回撥放在了chain陣列的後面,再此就不做分析啦!
總結一下,這個其實流程挺簡單的,就是把攔截器的回撥,放到傳送請求的promise之前,先執行。
關於取消請求的分析,傳送門,戳這裡。