01
前言
眾所周知在前后分離的背景下,一款優(yōu)秀的網(wǎng)絡(luò)請求庫是多么的重要,axios 現(xiàn)在幾乎已經(jīng)是一個項目開發(fā)的標(biāo)配了,無論是從vue 還是到 react 都可以看到它的身影??梢钥闯鲞@個庫的受歡迎程度。
這兩篇文章我們看一下 axios 的相關(guān)知識。從 import axios from 'axios' 再到 axios 的內(nèi)部源碼,帶大家看一下經(jīng)典庫的運(yùn)行流程。
相信大家認(rèn)真讀完之后肯定會有所收獲。
為了能幫助更多人學(xué)習(xí),如果有需要的可以加我的好友邀請你進(jìn)入前端學(xué)習(xí)交流微信群。
02
功能概覽
以下內(nèi)容來自 axios 官方
- Make XMLHttpRequests from the browser
- Make http requests from node.js
- Supports the Promise API
- Intercept request and response
- Transform request and response data
- Cancel requests
- Automatic transforms for JSON data
- Client side support for protecting against XSRF
03
**基本使用及問題思考
**
這里我們假定您已經(jīng)創(chuàng)建好了一個項目并且成功引入了 axios 依賴。
下面我們看一下在使用的 axios的時候一些步驟:
1、引入 axios 如下:
import axios from 'axios'
這行代碼背后做了什么?
我們稍后再來說
2、使用 axios
// 使用方式一
axios({
url: xxxx,
data: {}
}).then(res => {})
// 使用方式二
axios.[get|post|put]({
url: xxxx,
data: {}
}).then(res => {})
// 使用方式三
axios.request({
url: xxxx,
data: {}
}).then(res => {})
從上面的代碼可以看出 axios 的使用方式可以說是有很多種,而且配置也比較完善,我們引入的 axios 即可以直接調(diào)用,又可以以對象的方式調(diào)用其它方法。
那么axios到底是怎么做到的?稍后我們也會進(jìn)行講解。
3、最后再來看一下我個人認(rèn)為 axios 最優(yōu)秀的地方,執(zhí)行鏈、攔截器是怎么運(yùn)行的,運(yùn)行的流程是是怎么樣的。
下面我們一一解答,可以本篇文件講解不完,我會分成兩篇文章進(jìn)行說明。
04
**import axios from 'axios'背后做了什么
**
要了解這個問題,首先要知道 js 模塊化背后做了什么。
我們平時安裝的一些第三方依賴庫在我們 npm i 或者 npm install 之后都會被放到項目的 node_modules 文件夾下面。里面的內(nèi)容是非常非常多的,因為不僅僅是我們項目所需要依賴,還有依賴所需要依賴……直到把所有的依賴都加載完成之后才算完成。
當(dāng)打包工具執(zhí)行到 import axios from 'axios' 這行代碼之后,他會從 node_modules里面尋找 axios 目錄,如果沒有則報錯:找不到依賴,讓你進(jìn)行安裝。
如果已經(jīng)找到 axios 目錄,則會繼續(xù)找到該目錄下面的 package.json 清單文件。內(nèi)容如下(版本不同,內(nèi)容可能也會不同,不過大同小異)
在加載完 package.json之后,會找到 "main":"index.js" 這行配置。并且會認(rèn)定 "index.js" 為入口文件。執(zhí)行里面的代碼,如下:
從上面代碼可以看出,最后又加加載執(zhí)行 ./lib/axios
文件中的代碼。在加載 文件中的代碼時會找到默認(rèn)導(dǎo)出,如下:
至些,我們 import axios from 'axios' 背后的基本操作說完了,最后找到了
'/lib/axios'中的 module.exports = axios 這行代碼,拿到 axios 實例。
05
axios實例倒底是什么
從上面我們簡單的分析出 import axios from 'axios' 獲取實例的過程。然后就開始使用,但是有些朋友會有疑問,為什么 axios 即能當(dāng)方法調(diào)用也可以當(dāng)對象調(diào)用其方法屬性,非常靈活也非常方便。這背后是怎么做的?我們繼續(xù)分析
lib/axios
文件中暴露出一個默認(rèn)的實例對象 axios
。如下:
module.exports = axios;
看一下這個對象的定義:
// Create the default instance to be exported
var axios = createInstance(defaults);
是由一個方法生成,繼續(xù)看這個 createInstance
函數(shù)
function createInstance(defaultConfig) {
var context = new Axios(defaultConfig);
var instance = bind(Axios.prototype.request, context);
// Copy axios.prototype to instance
utils.extend(instance, Axios.prototype, context);
// Copy context to instance
utils.extend(instance, context);
return instance;
}
我們重點(diǎn)看一下:
var instance = bind(Axios.prototype.request, context);
instance實例由bind函數(shù)返回,bind函數(shù)內(nèi)容如下:
module.exports = function bind(fn, thisArg) {
return function wrap() {
var args = new Array(arguments.length);
for (var i = 0; i < args.length; i++) {
args[i] = arguments[i];
}
return fn.apply(thisArg, args);
};
};
到這里我們就應(yīng)該能看明白 bind 函數(shù)返回了一個名字叫 wrap的函數(shù)。也就是說上面的 instance 其實就是一個 函數(shù),這樣一步步的返回最終 lib/axios 默認(rèn)導(dǎo)出的就是一個函數(shù)類型的數(shù)據(jù)。
這也就說明了為什么 import axios from 'axios' 之后 我們可以直接當(dāng)函數(shù)進(jìn)行調(diào)用。因為默認(rèn)的 axios 本身就是函數(shù)肯定可以直接調(diào)用。
那問題又來了,為什么 axios 還可以當(dāng)成對象那樣可以調(diào)用某些屬性方法呢?
那就要看下 createInstance函數(shù)中的兩行行代碼了:
// Copy axios.prototype to instance
utils.extend(instance, Axios.prototype, context);
// Copy context to instance
utils.extend(instance, context);
這里涉及到了原型鏈的一些知識??梢岳斫獬砂?Axios.prototype 中的方法分配給了 instance 函數(shù)對象中,具體的過程如下:
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;
}
被分配方法有:
['post', 'put', 'patch']
['delete', 'get', 'head', 'options']
['request', 'getUri']
所以我們就可以像:axios.get 或者 axios.post 這樣調(diào)用了。
到目錄為止我們基本已經(jīng)梳理清楚了axios的加載過程,和基本的用法。
-
內(nèi)部
+關(guān)注
關(guān)注
0文章
9瀏覽量
18829 -
運(yùn)行
+關(guān)注
關(guān)注
0文章
25瀏覽量
15366 -
源碼
+關(guān)注
關(guān)注
8文章
626瀏覽量
28966
發(fā)布評論請先 登錄
相關(guān)推薦
評論