今日来看axios发送请求的部分,在axios中被称为适配器,即配置中的adapter属性.
adapter属性有两个值,在浏览器中使用xhr文件, 在node中
在xhr文件中,使用的其实就是ajax, 也就是XMLHttpRequest这个方法.
var request = new XMLHttpRequest();
当中就有我们很熟悉的open方法(request.open), onreadystatechange方法(request.onreadystatechange), onabort方法(request.onabort), 还有onerror, ontimeout等方法.文件添加了一些判断,使得请求更为完善.直接上代码,都看的懂
'use strict';
var utils = require('./../utils');
var settle = require('./../core/settle');
var cookies = require('./../helpers/cookies');
var buildURL = require('./../helpers/buildURL');
var buildFullPath = require('../core/buildFullPath');
var parseHeaders = require('./../helpers/parseHeaders');
var isURLSameOrigin = require('./../helpers/isURLSameOrigin');
var createError = require('../core/createError');
module.exports = function xhrAdapter(config) {
return new Promise(function dispatchXhrRequest(resolve, reject) {
var requestData = config.data;
var requestHeaders = config.headers;
if (utils.isFormData(requestData)) {
delete requestHeaders['Content-Type']; // Let the browser set it 让浏览器来设置
}
var request = new XMLHttpRequest();
// HTTP basic authentication http的基础验证
if (config.auth) {
var username = config.auth.username || '';
var password = config.auth.password ? unescape(encodeURIComponent(config.auth.password)) : '';
requestHeaders.Authorization = 'Basic ' + btoa(username + ':' + password);
}
var fullPath = buildFullPath(config.baseURL, config.url);
request.open(config.method.toUpperCase(), buildURL(fullPath, config.params, config.paramsSerializer), true);
// Set the request timeout in MS 设置请求超时
request.timeout = config.timeout;
// Listen for ready state 监听ready state
request.onreadystatechange = function handleLoad() {
if (!request || request.readyState !== 4) {
return;
}
// The request errored out and we didn't get a response, this will be
// handled by onerror instead 请求错误没有得到响应,将会被onerror处理
// With one exception: request that using file: protocol, most browsers
// will return status as 0 even though it's a successful request 有一个例外, 大多数浏览器即使请求成功也会返回状态为0
if (request.status === 0 && !(request.responseURL && request.responseURL.indexOf('file:') === 0)) {
return;
}
// Prepare the response 准备响应
var responseHeaders = 'getAllResponseHeaders' in request ? parseHeaders(request.getAllResponseHeaders()) : null;
var responseData = !config.responseType || config.responseType === 'text' ? request.responseText : request.response;
var response = {
data: responseData,
status: request.status,
statusText: request.statusText,
headers: responseHeaders,
config: config,
request: request
};
settle(resolve, reject, response);
// Clean up request 清除请求
request = null;
};
// Handle browser request cancellation (as opposed to a manual cancellation) 处理浏览器请求取消操作
request.onabort = function handleAbort() {
if (!request) {
return;
}
reject(createError('Request aborted', config, 'ECONNABORTED', request));
// Clean up request
request = null;
};
// Handle low level network errors 处理低级网络错误
request.onerror = function handleError() {
// Real errors are hidden from us by the browser 浏览器会为我们隐藏真正的错误
// onerror should only fire if it's a network error 如果是个网络错误会触发onerror
reject(createError('Network Error', config, null, request));
// Clean up request
request = null;
};
// Handle timeout 处理超时
request.ontimeout = function handleTimeout() {
var timeoutErrorMessage = 'timeout of ' + config.timeout + 'ms exceeded';
if (config.timeoutErrorMessage) {
timeoutErrorMessage = config.timeoutErrorMessage;
}
reject(createError(timeoutErrorMessage, config, 'ECONNABORTED',
request));
// Clean up request
request = null;
};
// 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. 在web worker或者rn中不会
if (utils.isStandardBrowserEnv()) {
// Add xsrf header
var xsrfValue = (config.withCredentials || isURLSameOrigin(fullPath)) && config.xsrfCookieName ?
cookies.read(config.xsrfCookieName) :
undefined;
if (xsrfValue) {
requestHeaders[config.xsrfHeaderName] = xsrfValue;
}
}
// Add headers to the request 给请求添加头部
if ('setRequestHeader' in request) {
utils.forEach(requestHeaders, function setRequestHeader(val, key) {
if (typeof requestData === 'undefined' && key.toLowerCase() === 'content-type') {
// Remove Content-Type if data is undefined 如果data是undefined,移除content-type
delete requestHeaders[key];
} else {
// Otherwise add header to the request 否则添加请求头
request.setRequestHeader(key, val);
}
});
}
// Add withCredentials to request if needed 如果需要则添加验证
if (!utils.isUndefined(config.withCredentials)) {
request.withCredentials = !!config.withCredentials;
}
// Add responseType to request if needed 如果需要,添加响应类型
if (config.responseType) {
try {
request.responseType = config.responseType;
} catch (e) {
// Expected DOMException thrown by browsers not compatible XMLHttpRequest Level 2.
// But, this can be suppressed for 'json' type as it can be parsed by default 'transformResponse' function.
if (config.responseType !== 'json') {
throw e;
}
}
}
// Handle progress if needed 处理过程
if (typeof config.onDownloadProgress === 'function') {
request.addEventListener('progress', config.onDownloadProgress);
}
// Not all browsers support upload events 不是所有的浏览器都支持上传事件
if (typeof config.onUploadProgress === 'function' && request.upload) {
request.upload.addEventListener('progress', config.onUploadProgress); // XMLHttpRequest的upload属性
}
if (config.cancelToken) {
// Handle cancellation 取消操作
config.cancelToken.promise.then(function onCanceled(cancel) {
if (!request) {
return;
}
request.abort();
reject(cancel);
// Clean up request
request = null;
});
}
if (!requestData) {
requestData = null;
}
// Send the request
request.send(requestData);
});
};
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。