API 解析
在Axios
中,可以使用多種方法請求資料,這讓Axios
變得及其簡單易用。
它既可以傳字串進 axios 中,也可以使用物件傳入。
使用 Axios 請求
axios({
url: 'localhost:3000',
data: {
firstName: 1,
lastName: 2
}
}).then(res => {
console.log(res);
});
// 這是使用字串的請求方式
axios('localhost:3000').then(res => {
console.log(res);
});
複製程式碼
使用 HTTP 的請求方法
axios.get('localhost:3000').then(res => {
console.log(res);
});
複製程式碼
兩種使用方法都可以使Axios
正常執行,而它用的是例項化物件,然後修改上下文的方法,可以讓它正常運轉。
建立 Axios 物件
在axios
的入口檔案處,axios
用到了許多方法,包括例項的繫結,以及屬性和方法的繼承。
繫結函式
function bind(fn, thisArg) {
// 閉包函式,返回已經修改好的作用域
return function wrap() {
var args = new Array(arguments.length);
for (var i = 0; i < args.length; i++) {
// 將引數拷貝到args上
args[i] = arguments[i];
}
// 執行一次函式
return fn.apply(thisArg, args);
};
}
複製程式碼
繼承屬性
function extend(a, b, thisArg) {
forEach(b, function assignValue(val, key) {
if (thisArg && typeof val === 'function') {
a[key] = bind(val, thisArg);
} else {
a[key] = val;
}
});
return a;
}
複製程式碼
例項化 Axios
new __Axios__ {
constructor(config) {
this.config = config;
}
request(config = this.config){
return config ? config : 'config'
}
}
// 例項化物件
const context = new __Axios__();
// 使用bind方法將原型鏈上的`request`指向是__Axios__上下文
const instance = bind(__Axios__.prototype.request,context);
// 將Axios的所有方法合併instance上去
extend(instance,Axios.prototype,context);
// 將Axios的所有屬性都合併到instance上去
extend(instance,context);
複製程式碼
這樣,Axios
既可以用get
,post
等方法獲取資料,又能使用Axios()
獲取資料。
攔截器
首先,寫一個攔截管理器的類。
class InterceptorManager {
constructor() {
this.handlers = [];
}
// 接收攔截或請求的方法
use(fulfilled, rejected) {
this.handlers.push({ fulfilled, rejected });
}
// 清除掉接收或請求的方法
reject(id) {
this.handlers[id] && this.handlers[id] = null;
}
// 將所有攔截器遍歷一次
forEach(fn) {
this.handlers.forEach(item => {
item && fn(item);
});
}
}
複製程式碼
例項化攔截器
接著,我們將攔截器例項化,類似下面的樣子:
class Axios {
constructor() {
this.interceptor = {
request: new InterceptorManager(),
response: new InterceptorManager()
};
}
}
複製程式碼
合成攔截器鏈
既然有了攔截器,那麼我們可以直接地傳送請求了。
思路是:
-
ResquestInterceptorFulfilled ---> ResquestInterceptorReject // 請求攔截器鏈
-
dispatchRequest ----> undefined // 分發請求
-
ResponseInterceptorFulfilled ---> ResponseInterceptorReject // 響應攔截器鏈
class Axios {
constructor() {
this.interceptor = {
request: new InterceptorManager(),
response: new InterceptorManager()
};
}
request() {
// dispatchRequest是指,分發的請求
const china = [dispathRequest, undefined];
const promise = Promise.resolve(config);
// 將請求攔截器推入鏈中
this.interceptor.request.forEach(interceptor => {
china.unshift(interceptor.fulfilled, interceptor.rejected);
});
// 將相應攔截器推入鏈中
this.interceptor.response.forEach(interceptor => {
china.push(interceptor.fulfilled, interceptor.rejected);
});
while (china.length) {
// 逐個遍歷,然後執行
promise = promise.then(chain.shift(), chain.shift());
}
return promise;
}
}
複製程式碼