发布时间:2023-03-27 12:30
function Axios(instanceConfig) {
//接受默认的配置参数
this.defaults = instanceConfig;
//定义请求和响应的拦截器
this.interceptors = {
request: new InterceptorManager(),
response: new InterceptorManager()
};
}
request
实际发送请求的方法
对用户传进来的配置参数进行合并
将用户配置的请求拦截(unshift)和响应拦截(push)添加到执行队列中
执行请求拦截函数---->发起请求----->执行响应拦截函数
Axios.prototype.request = function request(config) {
//这里就是对参数进行预处理,因为axios传入参数的方式有好几种
if (typeof config === \'string\') {
config = arguments[1] || {};
config.url = arguments[0];
} else {
config = config || {};
}
//将我们配置的参数和原始参数进行合并
config = mergeConfig(this.defaults, config);
// 设置请求方法
if (thod) {
config.methconfig.meod = config.method.toLowerCase();
} else if (this.defaults.method) {
config.method = this.defaults.method.toLowerCase();
} else {
config.method = \'get\';
}
//请求流程的调用链,处理函数都是成对出现,对应Promise的resolve和rejejct处理函数,
//当没有添加拦截器时,默认传入的是dispatchRequest和undefine
//dispatchRequest内部会发起真正XML的请求。
var chain = [dispatchRequest, undefined];
//将传入的配置进行预先设置,方便拦截器中获取
var promise = Promise.resolve(config);
//将用户添加的请求拦截函数放入chain中,采用的是unshift插入,在后面定义的请求拦截器反而最先执行
this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) {
chain.unshift(interceptor.fulfilled, interceptor.rejected);
});
//将用户添加的响应拦截函数放入chain中,采用的是push方式
this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) {
chain.push(interceptor.fulfilled, interceptor.rejected);
});
//循环执行弹出调用链中的方法,每个调用链中函数的返回值作为下一个函数的参数,最后promise拿到的就是最终的数据
while (chain.length) {
promise = promise.then(chain.shift(), chain.shift());
}
return promise;
};
添加其他原型方法
//将[\'delete\', \'get\', \'head\', \'options\']方法加入到Axios的原型中
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
}));
};
});
//将[\'post\', \'put\', \'patch\']方法加入到Axios的原型中
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
}));
};
});
axios实例
function createInstance(defaultConfig) {
//创建axios对象,将默认配置参数传入
var context = new Axios(defaultConfig);
//通过bind方法重新创建一个函数,并将Axios原型上的方法和属性复制给这个函数
var instance = bind(Axios.prototype.request, context);
utils.extend(instance, Axios.prototype, context);
utils.extend(instance, context);
return instance;
}
//创建请求方法,这个对象就是我们最终发送请求使用的方法,这一提醒下axios是一个函数。
var axios = createInstance(defaults);
bind
function bind(fn, thisArg){
return function wrap(...args){
return fn.apply(thisArg,args);
}
}
调用dispatchRequest发起请求
transformData
config.data = transformData(
config.data,
config.headers,
config.transformRequest
);
axios.get(\'xxxx\', {
transformResponse: axios.defaults.transformResponse.concat(function (data, headers) {
//....
return data;
})
})
adapter
var adapter = config.adapter || defaults.adapter;
var defaults = {
adapter: getDefaultAdapter(),
//.....
}
function getDefaultAdapter() {
var adapter;
//根据XMLHttpRequest判断当前是不是浏览器环境,如果不是就根据process判断是不是在node环境
if (typeof XMLHttpRequest !== \'undefined\') {
adapter = require(\'./adapters/xhr\');
} else if (typeof process !== \'undefined\' && Object.prototype.toString.call(process) === \'[object process]\') {
adapter = require(\'./adapters/http\');
}
return adapter;
}
浏览器环境:
module.exports = function xhrAdapter(config) {
return new Promise(function dispatchXhrRequest(resolve, reject) {
//...数据处理
var request = new XMLHttpRequest();
//...
request.open();
//设置超时时间
request.timeout = config.timeout;
request.onreadystatechange = function handleLoad() {
//...处理返回的数据
settle(resolve, reject, response);
request = null;
};
//监听中断操作
request.onabort = function handleAbort() {};
//监听错误
request.onerror = function handleError() {};
//监听超时
request.ontimeout = function handleTimeout() {};
if (requestData === undefined) {
requestData = null;
}
request.send(requestData);
});
};
adapter调用
return adapter(config).then(function onAdapterResolution(response) {
throwIfCancellationRequested(config);
//....对response进行处理
return response;
}, function onAdapterRejection(reason) {
if (!isCancel(reason)) {
throwIfCancellationRequested(config);
// Transform response data
if (reason && reason.response) {
//...对reason进行处理
}
}
return Promise.reject(reason);
});
监听上传下载
//监听下载进度
if (typeof config.onDownloadProgress === \'function\') {
request.addEventListener(\'progress\', config.onDownloadProgress);
}
//监听上传进度
if (typeof config.onUploadProgress === \'function\' && request.upload) {
request.upload.addEventListener(\'progress\', config.onUploadProgress);
}
中断请求
基本使用:
const CancelToken = axios.CancelToken;
const source = CancelToken.source();
axios.get(\'url\', {
cancelToken: source.token
}).then((res) => {
console.log(res)
}).catch((err) => {
console.log(err);
});
source.cancel(\'中断请求原因\');
CancelToken
function CancelToken(executor) {
var resolvePromise;
this.promise = new Promise(function promiseExecutor(resolve) {
//将promise的执行器暴露出去
resolvePromise = resolve;
});
var token = this;
executor(function cancel(message) {
if (token.reason) {
return;
}
token.reason = new Cancel(message);
resolvePromise(token.reason);
});
}
CancelToken.source
CancelToken.source = function source() {
var cancel;
var token = new CancelToken(function executor(c) {
cancel = c;
});
return {
token: token,
cancel: cancel
};
};
执行请求中断
if (config.cancelToken) {
config.cancelToken.promise.then(function onCanceled(cancel) {
if (!request) {
return;
}
//通过xhr.abort中断请求
request.abort();
reject(cancel);
request = null;
});
}