axios的核心

1. Interceptors 攔截器

axios 官網中對Interceptors 的使用方法如下: 用戶可以通過 then 方法為請求添加回調,而攔截器中的回調將在 then 中的回調之前執(zhí)行:

// Add a request interceptor
axios.interceptors.request.use(function (config) {
 // Do something before request is sent
 return config;
}, function (error) {
 // Do something with request error
 return Promise.reject(error);
});
// Add a response interceptor
axios.interceptors.response.use(function (response) {
 // Do something with response data
 return response;
}, function (error) {
 // Do something with response error
 return Promise.reject(error);
});

之后你可能需要能移除 Interceptors :

const myInterceptor = axios.interceptors.request.use(function () {/*...*/});
axios.interceptors.request.eject(myInterceptor);

也可以為axios實例添加一個Interceptors:

const instance = axios.create();
instance.interceptors.request.use(function () {/*...*/});

從其中的使用方法庆械,我們可以知道 request 攔截器需要在請求之前執(zhí)行盲憎,response 攔截器需要再請求之后執(zhí)行亏较。我們看一下axios的實現(xiàn)方式: 首先axios為攔截器定義了一個管理中心InterceptorManager:

function InterceptorManager() {
 this.handlers = [];
}
InterceptorManager.prototype.use = function use(fulfilled, rejected) {
 this.handlers.push({
 fulfilled: fulfilled,
 rejected: rejected
 });
 return this.handlers.length - 1;
};
InterceptorManager.prototype.forEach = function forEach(fn) {
 utils.forEach(this.handlers, function forEachHandler(h) {
 if (h !== null) {
 fn(h);
 }
 });
};

2.當實例化Axios時,分別創(chuàng)建一個request 和一個response攔截器:

function Axios(instanceConfig) {
 this.defaults = instanceConfig;
 this.interceptors = {
 request: new InterceptorManager(),
 response: new InterceptorManager()
 };
}

然后我們需要通過use來分別添加攔截器時,便將我們定義的resolve和reject收入對應的request和response中。在此之前讹蘑,我們需要對Promise有一個簡單的了解:

Promise then 方法返回的是一個新的 Promise 實例(注意,不是原來那個 Promise 實例)筑舅。因此可以采用鏈式寫法座慰,即 then 方法后面再調用另一個 then 方法。

getJSON("/posts.json").then(function(json) {
 return json.post;
}).then(function(post) {
 // ...
});

上面的代碼使用then方法翠拣,依次指定了兩個回調函數版仔。第一個回調函數完成以后,會將返回結果作為參數,傳入第二個回調函數蛮粮。采用鏈式的then益缎,可以指定一組按照次序調用的回調函數。這時然想,前一個回調函數莺奔,有可能返回的還是一個Promise對象(即有異步操作),這時后一個回調函數又沾,就會等待該Promise對象的狀態(tài)發(fā)生變化弊仪,才會被調用。

接下來杖刷,看看request方法是如何實現(xiàn)攔截器功能的:

Axios.prototype.request = function request(config) {
 ...
 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);
 });
 while (chain.length) {
 promise = promise.then(chain.shift(), chain.shift());
 }
 return promise;
};

首先定義了一個數組調用鏈chain,然后通過unshift將 request interceptors推入數組頭部驳癌,將response interceptors推入數組尾部滑燃。最后通過while這樣一個循環(huán)執(zhí)行promise.then來達到鏈式調用。 來看一張圖


通過巧妙的利用unshift颓鲜、push表窘、shift等數組隊列、棧方法甜滨,實現(xiàn)了請求攔截乐严、執(zhí)行請求、響應攔截的流程設定衣摩,注意無論是請求攔截還是響應攔截昂验,越先添加的攔截器總是越“貼近”執(zhí)行請求本身。

3. 自動轉換JSON數據

在默認情況下艾扮,axios將會自動的將傳入的data對象序列化為JSON字符串既琴,將響應數據中的JSON字符串轉換為JavaScript對象。這是一個非常實用的功能泡嘴,但實現(xiàn)起來非常簡單:

var defaults = {
 ...
 transformRequest: [function transformRequest(data, headers) {
 normalizeHeaderName(headers, 'Content-Type');
 if (utils.isFormData(data) ||
 utils.isArrayBuffer(data) ||
 utils.isBuffer(data) ||
 utils.isStream(data) ||
 utils.isFile(data) ||
 utils.isBlob(data)
 ) {
 return data;
 }
 if (utils.isArrayBufferView(data)) {
 return data.buffer;
 }
 if (utils.isURLSearchParams(data)) {
 setContentTypeIfUnset(headers, 'application/x-www-form-urlencoded;charset=utf-8');
 return data.toString();
 }
 // 這里對 object 做了轉換
 if (utils.isObject(data)) {
 setContentTypeIfUnset(headers, 'application/json;charset=utf-8');
 return JSON.stringify(data);
 }
 return data;
 }],
 transformResponse: [function transformResponse(data) {
 // 嘗試轉換 string -> json
 if (typeof data === 'string') {
 try {
 data = JSON.parse(data);
 } catch (e) { /* Ignore */ }
 }
 return data;
 }]
 ...
}

4. 支持客戶端 XSRF 攻擊防護

XSRF 攻擊甫恩,即“跨站請求偽造”(Cross Site Request Forgery)攻擊。通過竊取用戶cookie酌予,讓用戶在本機(即擁有身份 cookie 的瀏覽器端)發(fā)起用戶所不知道的請求磺箕。防護XSRF攻擊的一種方法是設置特殊的 xsrf token,axios實現(xiàn)了對這種方法的支持:


// 設置 xsrf 的 cookie 字段名和 header 字段名
{
 // `xsrfCookieName` is the name of the cookie to use as a value for xsrf token
 xsrfCookieName: 'XSRF-TOKEN', // default
 // `xsrfHeaderName` is the name of the http header that carries the xsrf token value
 xsrfHeaderName: 'X-XSRF-TOKEN', // default
}
module.exports = function xhrAdapter(config) {
 return new Promise(function dispatchXhrRequest(resolve, reject) {
 ...
 // Add xsrf header
 // This is only done if running in a standard browser environment.
 // Specifically not if we're in a web worker, or react-native.
 if (utils.isStandardBrowserEnv()) {
 var cookies = require('./../helpers/cookies');
 // Add xsrf header
 // 如果允許cookie跨域或者同源抛虫,首先會從cookie中讀取定義的token
 // 如果存在 xsrfValue 會將讀取到的 xsrfValue 攜帶進入 requestHeaders 中
 var xsrfValue = (config.withCredentials || isURLSameOrigin(config.url)) && config.xsrfCookieName ?
 cookies.read(config.xsrfCookieName) :
 undefined;
 if (xsrfValue) {
 requestHeaders[config.xsrfHeaderName] = xsrfValue;
 }
 }
 });
};
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末松靡,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子莱褒,更是在濱河造成了極大的恐慌击困,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,591評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異阅茶,居然都是意外死亡蛛枚,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,448評論 3 392
  • 文/潘曉璐 我一進店門脸哀,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蹦浦,“玉大人,你說我怎么就攤上這事撞蜂∶は猓” “怎么了?”我有些...
    開封第一講書人閱讀 162,823評論 0 353
  • 文/不壞的土叔 我叫張陵蝌诡,是天一觀的道長溉贿。 經常有香客問我,道長浦旱,這世上最難降的妖魔是什么宇色? 我笑而不...
    開封第一講書人閱讀 58,204評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮颁湖,結果婚禮上宣蠕,老公的妹妹穿的比我還像新娘。我一直安慰自己甥捺,他們只是感情好抢蚀,可當我...
    茶點故事閱讀 67,228評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著镰禾,像睡著了一般皿曲。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上羡微,一...
    開封第一講書人閱讀 51,190評論 1 299
  • 那天谷饿,我揣著相機與錄音,去河邊找鬼妈倔。 笑死博投,一個胖子當著我的面吹牛,可吹牛的內容都是我干的盯蝴。 我是一名探鬼主播毅哗,決...
    沈念sama閱讀 40,078評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼捧挺!你這毒婦竟也來了虑绵?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 38,923評論 0 274
  • 序言:老撾萬榮一對情侶失蹤闽烙,失蹤者是張志新(化名)和其女友劉穎翅睛,沒想到半個月后声搁,有當地人在樹林里發(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 45,334評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡捕发,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,550評論 2 333
  • 正文 我和宋清朗相戀三年疏旨,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片扎酷。...
    茶點故事閱讀 39,727評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡檐涝,死狀恐怖,靈堂內的尸體忽然破棺而出法挨,到底是詐尸還是另有隱情谁榜,我是刑警寧澤,帶...
    沈念sama閱讀 35,428評論 5 343
  • 正文 年R本政府宣布凡纳,位于F島的核電站窃植,受9級特大地震影響,放射性物質發(fā)生泄漏荐糜。R本人自食惡果不足惜撕瞧,卻給世界環(huán)境...
    茶點故事閱讀 41,022評論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望狞尔。 院中可真熱鬧,春花似錦巩掺、人聲如沸偏序。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,672評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽研儒。三九已至,卻和暖如春独令,著一層夾襖步出監(jiān)牢的瞬間端朵,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,826評論 1 269
  • 我被黑心中介騙來泰國打工燃箭, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留冲呢,地道東北人。 一個月前我還...
    沈念sama閱讀 47,734評論 2 368
  • 正文 我出身青樓招狸,卻偏偏與公主長得像敬拓,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子裙戏,可洞房花燭夜當晚...
    茶點故事閱讀 44,619評論 2 354

推薦閱讀更多精彩內容

  • vue-resourceVue.js是數據驅動的乘凸,這使得我們并不需要直接操作DOM,如果我們不需要使用jQuery...
    雪妮爸爸閱讀 856評論 0 0
  • vue-resource Vue.js是數據驅動的累榜,這使得我們并不需要直接操作DOM营勤,如果我們不需要使用jQuer...
    南臺觀蕓秀閱讀 417評論 0 1
  • Axios是近幾年非常火的HTTP請求庫,官網上介紹Axios 是一個基于 promise 的 HTTP 庫葛作,可以...
    milletmi閱讀 3,501評論 0 9
  • Vue.js 1.0 我們常使用 vue-resource (官方ajax庫), Vue 2.0 發(fā)布后作者宣告不...
    九四年的風閱讀 24,094評論 1 8
  • axios 基于promise用于瀏覽器和node.js的http客戶端 特點 支持瀏覽器和node.js 支持p...
    F_imok閱讀 2,189評論 0 0