1. 程式人生 > 其它 >Axios原始碼解析:攔截器

Axios原始碼解析:攔截器

[原文連結](https://github.com/AttemptWeb/Record/issues/26)

在Axios中攔截器是如何註冊和呼叫的呢?下面我們一起來看看

**瀏覽器端Axios**呼叫流程如下:

```
初始化Axios——> 註冊攔截器 ——> 請求攔截——> ajax請求 ——> 響應攔截 ——> 請求響應回撥
```

## Axios初始化

第一步:當然呼叫Axios請求時初始化了

```javascript
// 初始化Axios
function Axios(instanceConfig) {
this.defaults = instanceConfig;
this.interceptors = {
request: new InterceptorManager(),
response: new InterceptorManager()
};
}

module.exports = Axios;
```
InterceptorManager和InterceptorManager函式分別是是request攔截器和response攔截器,註冊攔截器回撥函式,**這裡只會講/*請求攔截器*/,因為響應攔截器基本也是這個流程**;這樣我們使用`axios.request.use`來新增攔截器函式時,實際就是`InterceptorManager`例項物件方法,那麼這裡`InterceptorManager`函式做了什麼呢?

## InterceptorManager註冊攔截函式

```javascript
function InterceptorManager() {
this.handlers = [];
}

//負責將攔截回撥函式儲存在handlers中
InterceptorManager.prototype.use = function use(fulfilled, rejected) {
this.handlers.push({
fulfilled: fulfilled,
rejected: rejected
});
return this.handlers.length - 1;
};
```
通過`axios.request.use`和`axios.response.use`請求、回撥攔截器新增攔截器,實際就是呼叫用`InterceptorManager`下的`use`方法,將回調函式儲存在`this.handlers`陣列中。

## 呼叫攔截器函式和請求函式

一下就是呼叫請求的實際程式碼,呼叫`Axios`下的`request`方法,同時也會先進行一次引數合併
```javascript
this.request(mergeConfig(config || {}, {
method: method,
url: url,
data: (config || {}).data
}));
```

下面就是`request`方法的實際程式碼,如下:
```javascript
Axios.prototype.request = function request(config) {
// dispatchRequest函式即ajax請求函式
var chain = [dispatchRequest, undefined];
var promise = Promise.resolve(config);

this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) {
chain.unshift(interceptor.fulfilled, interceptor.rejected);
});

this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) {
chain.push(interceptor.fulfilled, interceptor.rejected);
});

// 組裝 Promise 呼叫鏈,完成鏈式呼叫
while (chain.length) {
promise = promise.then(chain.shift(), chain.shift());
}

return promise;
};
```
在上面的程式碼中`chain`變數的實際值是這樣的:
```javascript
chain = [請求回撥攔截函式, 請求異常回調攔截函式, dispatchRequest, undefined, 響應回撥攔截函式, 響應異常回調攔截函式 ]
```
然後通過迴圈,使用`Promise鏈式呼叫`,來完成`請求攔截——> ajax請求 ——> 響應攔截`的功能,最後將結果`return`出來,非常的巧妙!!

看下面的就理解了?
![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/12cbfa5ce9aa4983b80a039eb5e5d83b~tplv-k3u1fbpfcp-zoom-1.image)
<center>(圖來源自轉載)</center>

參考:

[77.9K Star 的 Axios 專案有哪些值得借鑑的地方](https://juejin.im/post/6885471967714115597#heading-3)

[Axios攔截器核心原始碼](https://github.com/axios/axios/blob/master/lib/core/Axios.js#L27)