Axios源碼閱讀筆記#1 默認配置項

Promise based HTTP client for the browser and node.js

這是 Axios 的定義,Axios 是基於 Promise,用於HTTP客戶端——瀏覽器和 node.js 的庫 。Github:https://github.com/mzabriskie/axiosnode

 

官方文檔中 Axios 的 feature 有:react

  1)瀏覽器中使用 XMLHttpRequest;ios

  2)node.js 中使用 http 請求;git

  3)支持 Promise API;github

  4)可以攔截請求與響應;web

  5)可以轉換請求與響應的數據;面試

  6)請求可以取消;json

  7)自動轉換 JSON 數據;axios

  8)客戶端支持防範 XSRF;react-native

 

記得有一次面試中,面試官問到,Axios 是用什麼實現的,我回答說 Ajax。看面試官的表情,他彷佛認爲這個答案是錯的。後來仔細想了一下,Axios 是用 Ajax 實現異步請求的, 而異步操做則是基於 Promise 的。而 Axios 的目的呢,就是爲了在瀏覽器和 node.js 中,以統1、簡潔的方式使用 Ajax、處理回調。簡單的說,就是用 Promise 包裝了一下 AJAX(固然並無這麼簡單)。

 

最簡單的使用方法,僅僅須要向 Axios 傳遞請求地址,即可以發送一個 GET 請求。Ajax 中其它的配置 Axios 都已經默認設置好了。固然也能夠根據需求傳入 config,覆蓋默認配置項。默認配置定義在 /lib/defaults.js 中。

axios(url[, config])

 

default

var defaults = {
  adapter: getDefaultAdapter(),

  transformRequest: [...],

  transformResponse: [...],

  timeout: 0,          // 請求超時時間

  xsrfCookieName: 'XSRF-TOKEN',          // 用於獲取 cookie 中 'XSRF-TOKEN' 的值
  xsrfHeaderName: 'X-XSRF-TOKEN',        // 用於設置請求頭部

  maxContentLength: -1,

  validateStatus: function validateStatus(status) {
    return status >= 200 && status < 300;
  }
};

defaults.headers = {
  common: {
    'Accept': 'application/json, text/plain, */*'
  }
};

utils.forEach(['delete', 'get', 'head'], function forEachMehtodNoData(method) {
  defaults.headers[method] = {};
});

utils.forEach(['post', 'put', 'patch'], function forEachMethodWithData(method) {
  defaults.headers[method] = utils.merge(DEFAULT_CONTENT_TYPE);
});

module.exports = defaults;

 

adapter

瀏覽器和 node.js 實現異步請求的方式並不同,那麼 Axios 如何實現統一呢?

function getDefaultAdapter() {
  var adapter;
  if (typeof XMLHttpRequest !== 'undefined') {
    // For browsers use XHR adapter
    adapter = require('./adapters/xhr');
  } else if (typeof process !== 'undefined') {
    // For node use HTTP adapter
    adapter = require('./adapters/http');
  }
  return adapter;
}

var defaults = {
  adapter: getDefaultAdapter(),

  ...

}

 
 

module.exports = defaults;

 

在 defaults.js 中,經過分支選擇判斷,若 XMLHttpRequest 存在,表明當前環境爲瀏覽器, 則異步請求將使用 XHR;不然,若存在 process,表明當前環境爲 node.js,則使用 HTTP。

 

Axios 基於 Promise 就體如今 adapter。不管是 XHR 仍是 HTTP,都是通過 Promise 包裝的,getDefaultAdapter() 返回的都是一個 Promise 對象。若是但願使用 fetch 或者其餘自定義,在 config 中傳入 adapter 就能夠了,參考 gthub 的 /lib/adapters/README.md 的示例, adapter 應該是一個 Promise 對象。

 

XHR

在瀏覽器中 Axios 使用的是 XMLHttpRequest。咱們一般會將 Ajax 等同於 XMLHttpRequest,但二者並不同。《JavaScript 高級程序設計》中提到,「Ajax 技術的核心是 XMLHttpRequest 對象(簡稱XHR)」。在 xhr.js 中,主要是對 XHR請求以及響應數據的一些封裝,使它可以兼容 IE8/9。

 

上文提到客戶端支持 XSRF防範  ,是在 xhr.js 中實現。往請求頭中插入‘X-XSRF-TOKEN’字段。

    // 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
      var xsrfValue = (config.withCredentials || isURLSameOrigin(config.url)) && config.xsrfCookieName ?
          cookies.read(config.xsrfCookieName) :
          undefined;

      if (xsrfValue) {
     // 默認配置中 xsrfHeadeName: 'X-XSRF-TOKEN' requestHeaders[config.xsrfHeaderName]
= xsrfValue; } }

 

transformRequest

transformRequest 是根據請求數據的類型對數據進行轉換,並改變 Content-Type。默認的  Content-Type 爲 ‘application/x-www-form-urlencoded’
transformRequest: [function transformRequest(data, headers) {
    normalizeHeaderName(headers, 'Content-Type');
    if (utils.isFormData(data) ||
      utils.isArrayBuffer(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();
    }
    if (utils.isObject(data)) {
      setContentTypeIfUnset(headers, 'application/json;charset=utf-8');
      return JSON.stringify(data);
    }
    return data;
  }],

 

 

transformResponse
transformResponse 默認將響應數據轉換爲 JSON格式。
transformResponse: [function transformResponse(data) {
    /*eslint no-param-reassign:0*/
    if (typeof data === 'string') {
    // var PROTECTION_PREFIX = /^\)\]\}',?\n/; data
= data.replace(PROTECTION_PREFIX, ''); try { data = JSON.parse(data); } catch (e) { /* Ignore */ } } return data; }],

 

瞭解 Axios 的默認配置項以後,就明白如何經過 config 來自定義請求了。
相關文章
相關標籤/搜索