# axios源码分析
axios既支持浏览器,也可以在node项目中使用
- 从浏览器中创建 XMLHttpRequests (opens new window)
- 从 node.js 创建 http (opens new window) 请求
# 目录结构
|--dist 
|--lib
| |-- adapters
| | |-- http.js
| | |-- xhr.js
| |-- cancel
| | |-- cancel.js
| | |-- cancelToken.js
| | |-- isCancel.js
| |-- core
| | |-- Axios.js
| | |-- createError.js
| | |-- dispatchRequest.js
| | |-- enhanceError.js
| | |-- interceptorManager.js
| | |-- settle.js  // response处理
| | |-- transformData.js // transformRequest/transformResponse的处理
| |-- helpers
| | |-- bind.js 
| | |-- buildURL.js  // params参数的处理
| | |-- combineRULs.js
| | |-- cookies.js
| | |-- deprecatedMethod.js
| | |-- isAbsoluteURL.js
| | |-- isURLSameOrigin.js
| | |-- normailizeHeaderName.js
| | |-- parseHeaders.js
| | |-- spread.js
| |-- axios.js
|-- default.js
|-- utils.js
|-- index.js
|-- index.d.ts
# 源码分析
- url地址拼接处理:helpers/buildURL.js
- 头部处理 配置会以一个优先顺序进行合并。这个顺序是:在 lib/defaults.js 找到的库的默认值,然后是实例的 defaults 属性,最后是请求的 config 参数。后者将优先于前者
index.js--> axios.js --> Axios.js
// axios.js(入口文件) //->Axios.js(defaults.js) //->dispatchRequest.js(chain[],interceptors.request放在组件面) //->
# 核心代码(Axios.js)
Axios.prototype.request = function request(config) {
  /*eslint no-param-reassign:0*/
  // Allow for axios('example/url'[, config]) a la fetch API
  if (typeof config === 'string') {
    config = utils.merge({
      url: arguments[0]
    }, arguments[1]);
  }
  config = utils.merge(defaults, {method: 'get'}, this.defaults, config);
  config.method = config.method.toLowerCase();
  // Hook up interceptors middleware
  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;
};
dispatchRequest.js
module.exports = function dispatchRequest(config) {
  throwIfCancellationRequested(config);
  // Support baseURL config
  if (config.baseURL && !isAbsoluteURL(config.url)) {
    config.url = combineURLs(config.baseURL, config.url);
  }
  // Ensure headers exist
  config.headers = config.headers || {};
  // Transform request data
  config.data = transformData(
    config.data,
    config.headers,
    config.transformRequest
  );
  // Flatten headers
  config.headers = utils.merge(
    config.headers.common || {},
    config.headers[config.method] || {},
    config.headers || {}
  );
  utils.forEach(
    ['delete', 'get', 'head', 'post', 'put', 'patch', 'common'],
    function cleanHeaderConfig(method) {
      delete config.headers[method];
    }
  );
 // 执行ajax请求
  var adapter = config.adapter || defaults.adapter;
  return adapter(config).then(function onAdapterResolution(response) {
    throwIfCancellationRequested(config);
    // Transform response data
    response.data = transformData(
      response.data,
      response.headers,
      config.transformResponse
    );
    return response;
  }, function onAdapterRejection(reason) {
    if (!isCancel(reason)) {
      throwIfCancellationRequested(config);
      // Transform response data
      if (reason && reason.response) {
        reason.response.data = transformData(
          reason.response.data,
          reason.response.headers,
          config.transformResponse
        );
      }
    }
    return Promise.reject(reason);
  });
};
# AJAX
header的Content-Type(setRequestHeader)
- application/x-www-form-urlencoded format 
- application/json 
- URLSearchParams https://developer.mozilla.org/zh-CN/docs/Web/API/URLSearchParams 
- Accept 
// 默认:
// 设置不同方法请求的内容类型
// 在default.js里面会对Data的类型进行判断,设置相应的Content-type
// xhr.js->adapter->put、post等:如果isFormData 会删除 Content-type,Let the browser set it
// dispatchRequest里面会在post里面的方法,拍平到headers下面,然后删除对用的方法下的头部设置项
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8'
axios.defaults.headers.get['x-x'] = 'get-only'
axios.defaults.headers.put['x-x-x'] = 'put-only'
// request配置
axios.interceptors.request.use((config) => {
  // get请求:发送的数据data="undefined",header数据的content-type会被删除,
  // 如果是post、put请求:以下设置则会生效。
  // content-type设置发送请求的数据类型,不设置default.js会对发送的data类型进行判断,然后添加对应的类型
  // 这个应该是在default.js执行之后,在执行
  config.headers['content-type'] = 'application/json';
  return config;
});