1、axios(config)
- 使用
// 发送 POST 请求
axios({
method: 'post',
url: '/user/12345',
data: {
firstName: 'Fred',
lastName: 'Flintstone'
}
});
- 核心源码
/* 1 axios */
/**
* 创建Axios实例
* @param {Object} defaultConfig 实例的默认配置
* @return {Axios} Axios的新实例
*/
function createInstance(defaultConfig) {
var context = new Axios(defaultConfig);
/* 程序员调用的axios.request(config) */
var instance = bind(Axios.prototype.request, context);
// 复制axios的原型到实例上
utils.extend(instance, Axios.prototype, context);
// 将上下文复制到实例
utils.extend(instance, context);
return instance;
}
//创建要导出的默认实例
var axios = createInstance(defaults);
/* 4 Axios */
/**
* 发送请求
* @param {Object} config 此请求的特定配置(merged with this.defaults)
*/
Axios.prototype.request = function request(config) {
if (typeof config === 'string') {
// eg: axios.request("localhost://xxx")
config = arguments[1] || {};
config.url = arguments[0];
} else {
config = config || {};
}
// 合并默认config和程序员传递的config
config = mergeConfig(this.defaults, config);
// 设置config的method,转换为小写
if (config.method) {
config.method = config.method.toLowerCase();
} else if (this.defaults.method) {
config.method = this.defaults.method.toLowerCase();
} else {
// 默认为get请求
config.method = 'get';
}
// 连接拦截器中间件
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);
});
// dispatchReuest发送请求永远会在数组的中间
while (chain.length) {
promise = promise.then(chain.shift(), chain.shift());
}
return promise;
};
2、axios(url[, config])
- 使用
// 发送 GET 请求(默认的方法)
axios('/user/12345');
- 核心源码
/* 4 Axios */
Axios.prototype.request = function request(config) {
if (typeof config === 'string') {
// eg: axios.request("localhost://xxx")
config = arguments[1] || {};
config.url = arguments[0];
} else {
config = config || {};
}
// ...
}
3、请求方法别名
- axios.request(config)
- axios.get(url[, config])
- axios.delete(url[, config])
- axios.head(url[, config])
- axios.options(url[, config])
- axios.post(url[, data[, config]])
- axios.put(url[, data[, config]])
- axios.patch(url[, data[, config]])
注意:在使用别名方法时, url、method、data 这些属性都不必在配置中指定。
- 核心源码
/* 4 Axios */
// 为支持的请求方法提供别名 内部实现都是调用Axios.prototype.request方法
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
}));
};
});
4、axios.all(iterable)
- 核心源码
/* 1 axios */
// 全部暴露/扩散
axios.all = function all(promises) {
return Promise.all(promises);
};
5、axios.spread(callback)
- 核心源码
/* 25 spread */
/***/ (function(module, exports) {
module.exports = function spread(callback) {
return function wrap(arr) {
return callback.apply(null, arr);
};
};
/***/ })
6、axios.create([config])
- 使用
const instance = axios.create({
baseURL: 'https://some-domain.com/api/',
timeout: 1000,
headers: {'X-Custom-Header': 'foobar'}
});
- 核心源码
/* 1 axios */
/* 程序员调用的axios.create() */
axios.create = function create(instanceConfig) {
return createInstance(mergeConfig(axios.defaults, instanceConfig));
};
// 返回的实例可以调用
// axios#request(config)
// axios#get(url[, config])
// axios#delete(url[, config])
// axios#head(url[, config])
// axios#options(url[, config])
// axios#post(url[, data[, config]])
// axios#put(url[, data[, config]])
// axios#patch(url[, data[, config]])
7、响应结构
- 使用
{
// `data` 由服务器提供的响应
data: {},
// `status` 来自服务器响应的 HTTP 状态码
status: 200,
// `statusText` 来自服务器响应的 HTTP 状态信息
statusText: 'OK',
// `headers` 服务器响应的头
headers: {},
// `config` 是为请求提供的配置信息
config: {},
// 'request'
// `request` is the request that generated this response
// It is the last ClientRequest instance in node.js (in redirects)
// and an XMLHttpRequest instance the browser
request: {}
}
- 核心源码
/* 12 adapter:适配器 */
// response数据
var response = {
data: responseData,
status: request.status,
statusText: request.statusText,
headers: responseHeaders,
config: config,
request: request
};
settle(resolve, reject, response);
/* 13 settle:结束请求*/
'use strict';
var createError = __webpack_require__(14);
/**
* 基于响应状态解决或拒绝承诺。
*
* @param {Function} resolve resolve
* @param {Function} reject reject
* @param {object} response 返回值
*/
module.exports = function settle(resolve, reject, response) {
var validateStatus = response.config.validateStatus;
if (!validateStatus || validateStatus(response.status)) {
resolve(response);
} else {
reject(createError(
'Request failed with status code ' + response.status,
response.config,
null,
response.request,
response
));
}
};
/* 10 defaultConfig */
// 创建axios的默认参数
var defaults = {
// ...
// 验证状态 http请求的状态码
validateStatus: function validateStatus(status) {
return status >= 200 && status < 300;
}
};
// ...
8、全局的 axios 默认值
- 使用
axios.defaults.baseURL = 'https://api.example.com';
axios.defaults.headers.common['Authorization'] = AUTH_TOKEN;
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
- 核心源码
/* 1 axios */
/**
* 创建Axios实例
*
* @param {Object} defaultConfig 实例的默认配置
* @return {Axios} Axios的新实例
*/
function createInstance(defaultConfig) {
var context = new Axios(defaultConfig);
// ...
// 将上下文复制到实例
utils.extend(instance, context);
return instance;
}
/* 4 Axios */
/**
* Axios构造函数
*
* @param {Object} instanceConfig 实例的默认配置
*/
function Axios(instanceConfig) {
this.defaults = instanceConfig;
// ...
}
9、拦截器
在请求或响应被 then 或 catch 处理前拦截它们。
- 使用
// 添加请求拦截器
axios.interceptors.request.use(function (config) {
// 在发送请求之前做些什么
return config;
}, function (error) {
// 对请求错误做些什么
return Promise.reject(error);
});
// 添加响应拦截器
axios.interceptors.response.use(function (response) {
// 对响应数据做点什么
return response;
}, function (error) {
// 对响应错误做点什么
return Promise.reject(error);
});
如果你想在稍后移除拦截器,可以这样:
const myInterceptor = axios.interceptors.request.use(function () {/*...*/});
axios.interceptors.request.eject(myInterceptor);
- 核心源码
/* 4 Axios */
/**
* 发送请求
* @param {Object} config 此请求的特定配置(merged with this.defaults)
*/
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);
});
// dispatchReuest发送请求永远会在数组的中间
while (chain.length) {
promise = promise.then(chain.shift(), chain.shift());
}
return promise;
}
/* 6 InterceptorManager:拦截器 */
'use strict';
var utils = __webpack_require__(2);
function InterceptorManager() {
this.handlers = [];
}
/**
* 向堆栈添加一个新的拦截器
*
* @param {Function} fulfilled 处理“then”for a“Promise”的函数`
* @param {Function} rejected 为一个承诺处理“拒绝”的函数`
*
* @return {Number} 用于稍后删除拦截器的ID
*/
InterceptorManager.prototype.use = function use(fulfilled, rejected) {
this.handlers.push({
fulfilled: fulfilled,
rejected: rejected
});
return this.handlers.length - 1; // 返回数组的索引,便于移除
};
/**
* 从堆栈中移除拦截器
*
* @param {Number} id 使用返回的ID
*/
InterceptorManager.prototype.eject = function eject(id) {
if (this.handlers[id]) {
this.handlers[id] = null;
}
};
/**
* 迭代所有注册的拦截器
*
* 此方法对于跳过任何可能已变为“null”并调用“eject”的侦听器特别有用。
*
* @param {Function} fn 为每个拦截器调用的函数
*/
InterceptorManager.prototype.forEach = function forEach(fn) {
utils.forEach(this.handlers, function forEachHandler(h) {
if (h !== null) {
fn(h);
}
});
};
module.exports = InterceptorManager;
10、取消
- 使用
const CancelToken = axios.CancelToken;
const source = CancelToken.source();
axios.get('/user/12345', {
cancelToken: source.token
}).catch(function(thrown) {
if (axios.isCancel(thrown)) {
console.log('Request canceled', thrown.message);
} else {
// 处理错误
}
});
axios.post('/user/12345', {
name: 'new name'
}, {
cancelToken: source.token
})
// 取消请求(message 参数是可选的)
source.cancel('Operation canceled by the user.');
- 核心源码
/* 24 CancelToken */
/**
* “CancelToken”是可用于请求取消操作的对象。
*
* @class
* @param {Function} executor The executor function.
*/
function CancelToken(executor) {
if (typeof executor !== 'function') {
throw new TypeError('executor must be a function.');
}
var resolvePromise;
this.promise = new Promise(function promiseExecutor(resolve) {
resolvePromise = resolve;
});
var token = this;
executor(function cancel(message) {
if (token.reason) {
// 已请求取消
return;
}
token.reason = new Cancel(message);
resolvePromise(token.reason);
});
}
/**
* 返回一个对象,该对象包含一个新的“CancelToken”和一个在调用时取消“CancelToken”的函数。
*/
CancelToken.source = function source() {
var cancel;
var token = new CancelToken(function executor(c) {
cancel = c;
});
return {
token: token,
cancel: cancel
// cancel()执行时,取消请求;配合
// config.cancelToken.promise.then(function onCanceled(cancel) {
// if (!request) {
// return;
// }
// request.abort();
// reject(cancel);
// // 清理请求
// request = null;
// });
// 使用。
// config.cancelToken.promise.then会在cancel()执行时,触发resolvePromise Promise.resolve函数后,再执行
// 所以,cancel()不执行时,不会取消请求
};
};
/* 23 Cancel:取消*/
/**
* “Cancel”是取消操作时引发的对象。
*
* @class
* @param {string=} message The message.
*/
function Cancel(message) {
this.message = message;
}
/* 12 adapter:适配器 */
if (config.cancelToken) {
// 处理取消
config.cancelToken.promise.then(function onCanceled(cancel) {
if (!request) {
return;
}
request.abort();
reject(cancel);
// 清理请求
request = null;
});
}