) {
reject
(
createError
(
'timeout of '
+ config.
timeout
+
'ms exceeded'
, config,
'ECONNABORTED'
,
request));
request =
null
;
if
(utils.
isStandardBrowserEnv
()) {
var
cookies =
require
(
'./../helpers/cookies'
);
var
xsrfValue = (config.
withCredentials
||
isURLSameOrigin
(config.
url
)) && config.
xsrfCookieName
?
cookies.
read
(config.
xsrfCookieName
) :
undefined
;
if
(xsrfValue) {
requestHeaders[config.
xsrfHeaderName
] = xsrfValue;
if
(
'setRequestHeader'
in
request) {
utils.
forEach
(requestHeaders,
function
setRequestHeader
(
val, key
) {
if
(
typeof
requestData ===
'undefined'
&& key.
toLowerCase
() ===
'content-type'
) {
delete
requestHeaders[key];
}
else
{
request.
setRequestHeader
(key, val);
if
(config.
withCredentials
) {
request.
withCredentials
=
true
;
if
(config.
responseType
) {
try
{
request.
responseType
= config.
responseType
;
}
catch
(e) {
if
(config.
responseType
!==
'json'
) {
throw
e;
if
(
typeof
config.
onDownloadProgress
===
'function'
) {
request.
addEventListener
(
'progress'
, config.
onDownloadProgress
);
if
(
typeof
config.
onUploadProgress
===
'function'
&& request.
upload
) {
request.
upload
.
addEventListener
(
'progress'
, config.
onUploadProgress
);
if
(config.
cancelToken
) {
config.
cancelToken
.
promise
.
then
(
function
onCanceled
(
cancel
) {
if
(!request) {
return
;
request.
abort
();
reject
(cancel);
request =
null
;
if
(requestData ===
undefined
) {
requestData =
null
;
request.
send
(requestData);
复制代码
/lib/core/dispatchRequest.js
dispatchRequest.js文件是axios源码中实际调用请求的地方。
var utils = require('./../utils')
var transformData = require('./transformData')
var isCancel = require('../cancel/isCancel')
var defaults = require('../defaults')
var isAbsoluteURL = require('./../helpers/isAbsoluteURL')
var combineURLs = require('./../helpers/combineURLs')
// 判断请求是否已被取消,如果已经被取消,抛出已取消
function throwIfCancellationRequested(config) {
if (config.cancelToken) {
config.cancelToken.throwIfRequested()
module.exports = function dispatchRequest(config) {
throwIfCancellationRequested(config)
// 如果包含baseUrl, 并且不是config.url绝对路径,组合baseUrl以及config.url
if (config.baseURL && !isAbsoluteURL(config.url)) {
// 组合baseURL与url形成完整的请求路径
config.url = combineURLs(config.baseURL, config.url)
config.headers = config.headers || {}
// 使用/lib/defaults.js中的transformRequest方法,对config.headers和config.data进行格式化
// 比如将headers中的Accept,Content-Type统一处理成大写
// 比如如果请求正文是一个Object会格式化为JSON字符串,并添加application/json
// 等一系列操作
config.data = transformData(
config.data,
config.headers,
config.transformRequest
// 合并不同配置的headers,config.headers的配置优先级更高
config.headers = utils.merge(
config.headers.common || {},
config.headers[config.method] || {},
config.headers || {}
// 删除headers中的method属性
utils.forEach(
['delete', 'get', 'head', 'post', 'put', 'patch', 'common'],
function cleanHeaderConfig(method) {
delete config.headers[method]
// 如果config配置了adapter,使用config中配置adapter的替代默认的请求方法
var adapter = config.adapter || defaults.adapter
// 使用adapter方法发起请求(adapter根据浏览器环境或者Node环境会有不同)
return adapter(config).then(
// 请求正确返回的回调
function onAdapterResolution(response) {
// 判断是否以及取消了请求,如果取消了请求抛出以取消
throwIfCancellationRequested(config)
// 使用/lib/defaults.js中的transformResponse方法,对服务器返回的数据进行格式化
// 例如,使用JSON.parse对响应正文进行解析
response.data = transformData(
response.data,
response.headers,
config.transformResponse
return response
// 请求失败的回调
function onAdapterRejection(reason) {
if (!isCancel(reason)) {
throwIfCancellationRequested(config)
if (reason && reason.response) {
reason.response.data = transformData(
reason.response.data,
reason.response.headers,
config.transformResponse
return Promise.reject(reason)
复制代码
/lib/core/InterceptorManager.js
InterceptorManager.js文件中定义了axios拦截器类。包含了拦截器的添加,删除,循环拦截器。无论是响应拦截器还是请求拦截器,都是使用数组进行存储的。
var utils = require('./../utils');
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.eject = function eject(id) {
if (this.handlers[id]) {
this.handlers[id] = null;
InterceptorManager.prototype.forEach = function forEach(fn) {
utils.forEach(this.handlers, function forEachHandler(h) {
if (h !== null) {
fn(h);
module.exports = InterceptorManager;
复制代码
/lib/core/Axios.js
Axios.js文件中定义了Axios实例上的request,get,post,delete方法。get,post,delete等方法均是基于Axios.prototype.request的封装📦。在Axios.prototype.request中会依次执行请求拦截器,dispatchRequest(实际发起),响应拦截器。整体的流程如👆上图所示。
var utils = require('./../utils')
var buildURL = require('../helpers/buildURL')
var InterceptorManager = require('./InterceptorManager')
var dispatchRequest = require('./dispatchRequest')
var mergeConfig = require('./mergeConfig')
function Axios(instanceConfig) {
// Axios的配置
this.defaults = instanceConfig
// 拦截器
this.interceptors = {
request: new InterceptorManager(), // 请求拦截器
response: new InterceptorManager() // 响应拦截器
Axios.prototype.request = function request(config) {
// 如果config是一个字符串,把字符串当作请求的url地址
if (typeof config === 'string') {
config = arguments[1] || {}
config.url = arguments[0]
} else {
config = config || {}
// 合并配置
config = mergeConfig(this.defaults, config)
// 如果没有指定请求方法,使用get方法
config.method = config.method ? config.method.toLowerCase() : 'get'
var promise = Promise.resolve(config)
// 将请求拦截器,和响应拦截器,以及实际的请求(dispatchRequest)的方法组合成数组,类似如下的结构
// [请求拦截器1success, 请求拦截器1error, 请求拦截器2success, 请求拦截器2error, dispatchRequest, undefined, 响应拦截器1success, 响应拦截器1error]
var chain = [dispatchRequest, undefined]
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)
// 开始执行整个请求流程(请求拦截器->dispatchRequest->响应拦截器)
// 流程可以理解为上图⬆️
while (chain.length) {
promise = promise.then(chain.shift(), chain.shift())
return promise
Axios.prototype.getUri = function getUri(config) {
config = mergeConfig(this.defaults, config)
return buildURL(config.url, config.params, config.paramsSerializer).replace(/^\?/, '')
// 基于Axios.prototype.request封装其他方法
// 将delete,get,head,options,post,put,patch添加到Axios.prototype的原型链上
// Axios.prototype.delete =
// Axios.prototype.get =
// Axios.prototype.head =
// Axios.prototype.options =
// ...
utils.forEach(['delete', 'get', 'head', 'options'], function forEachMethodNoData(method) {
Axios.prototype[method] = function(url, config) {
return this.request(utils.merge(config || {}, {
method: method,
url: url
}))
utils.forEach(['post', 'put', 'patch'], function forEachMethodWithData(method) {
Axios.prototype[method] = function(url, data, config) {
return this.request(utils.merge(config || {}, {
method: method,
url: url,
data: data
}))
module.exports = Axios
复制代码
/lib/defaults.js
defaults.js文件中配置了,axios默认的请求头、不同的环境下axios默认使用的请求方法、格式化请求正文的方法,格式化响应正文方法等内容
var utils = require('./utils');
var normalizeHeaderName = require('./helpers/normalizeHeaderName');
var DEFAULT_CONTENT_TYPE = {
'Content-Type': 'application/x-www-form-urlencoded'
function setContentTypeIfUnset(headers, value) {
if (!utils.isUndefined(headers) && utils.isUndefined(headers['Content-Type'])) {
headers['Content-Type'] = value;
function getDefaultAdapter() {
var adapter;
if (typeof process !== 'undefined' && Object.prototype.toString.call(process) === '[object process]') {
adapter = require('./adapters/http');
} else if (typeof XMLHttpRequest !== 'undefined') {
adapter = require('./adapters/xhr');
return adapter;
var defaults = {
adapter: getDefaultAdapter(),
transformRequest: [
function transformRequest(data, headers) {
normalizeHeaderName(headers, 'Accept');
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();
if (utils.isObject(data)) {
setContentTypeIfUnset(headers, 'application/json;charset=utf-8');
return JSON.stringify(data);
return data;
transformResponse: [
function transformResponse(data) {
if (typeof data === 'string') {
try {
data = JSON.parse(data);
} catch (e) { }
return data;
timeout: 0,
xsrfCookieName: '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 forEachMethodNoData(method) {
defaults.headers[method] = {};
utils.forEach(['post', 'put', 'patch'], function forEachMethodWithData(method) {
defaults.headers[method] = utils.merge(DEFAULT_CONTENT_TYPE);
module.exports = defaults;
复制代码
/lib/axios.js
axios.js文件是axios工具库的入口方法,在axios.js
var utils = require('./utils')
var bind = require('./helpers/bind')
var Axios = require('./core/Axios')
var mergeConfig = require('./core/mergeConfig')
var defaults = require('./defaults')
// 创建axios实例
function createInstance(defaultConfig) {
var context = new Axios(defaultConfig)
// 更改Axios.prototype.request的this,执行context实例
// instance等于Axios.prototype.request方法
var instance = bind(Axios.prototype.request, context)
// 将Axios.prototype,context上的属性合并到instance
// instance.get = Axios.prototype.get
// instance.defaults = context.defaults
// ...
utils.extend(instance, Axios.prototype, context)
utils.extend(instance, context)
return instance
// axios会直接对使用者暴露一个axios.request的方法,所以我们在使用axios的时候可以这样使用。不需要new一个axios的实例
// import axios from 'axios'
// axios.get('/info')
var axios = createInstance(defaults)
axios.Axios = Axios
// axios.create可以根据用户自定义的config生成一个新的axios实例
axios.create = function create(instanceConfig) {
return createInstance(mergeConfig(axios.defaults, instanceConfig))
axios.Cancel = require('./cancel/Cancel')
axios.CancelToken = require('./cancel/CancelToken')
axios.isCancel = require('./cancel/isCancel')
axios.all = function all(promises) {
return Promise.all(promises)
axios.spread = require('./helpers/spread')
module.exports = axios
module.exports.default = axios
复制代码
-
9552
-
答案cp3
JavaScript
axios
-
2760
-
zhangbao90s
JavaScript