Open py-tofee opened 3 years ago
调用axios()并不会立即发送请求,执行顺序说明:[请求拦截器2-成功, 请求拦截器2-失败, 请求拦截器1-成功, 请求拦截器1-失败, dispatchRequest, undefined, 响应拦截器1-成功, 响应拦截器1-失败, 响应拦截器2-成功, 响应拦截器2-失败],请求过程是由promise串联起来的,每一步都返回一个promise,请求拦截器之间传递的是config,发送请求之后,响应拦截器之间传递的是response;axios()即调用Axios.prototype.request()
方法,最后返回一个promise,交由用户去处理返回的响应数据;
在dispatchRequest中,处理请求URL(整合baseURL和config.url),处理请求数据,合并请求头信息headers,调用合适的适配器adapter config.adapter || defaults.adapter
,发送请求,并处理响应数据,最后返回一个promise
let cancel;
// 请求之前,判断cancel是否为null
if (cancel && typeof cancel === 'function') {
cancel('取消请求')
}
axios({
url: '',
cancelToken: new axios.CancelToken(function executor(c) {
cancel = c; // 保存取消函数到cancel变量中,用于之后可能要取消当前请求
})
}).then(
// 请求响应后,将cancel置空
response => {
cancel = null
},
error => {
cancel = null
}
)
原理:
axios.CancelToken = require('./cancel/CancelToken');
CancelToken函数,接收一个执行函数作为参数,执行new axios.CancelToken(executor),返回一个实例cancelToken,这个实例上有一个promise属性,将这个promise的resolve暴露给resolvePromise;调用传进来的执行函数executor(function cancel() {})
,将取消请求的cancel函数暴露出去,由用户保存,例如上例中的cancel变量,当用户调用cancel()时,会执行resolvePromise;
CancelToken函数:
function CancelToken(executor) {
if (typeof executor !== 'function') {
throw new TypeError('executor must be a function.');
}
var resolvePromise;
// 添加实例属性promise
this.promise = new Promise(function promiseExecutor(resolve) {
resolvePromise = resolve;
});
var token = this;
executor(function cancel(message) {
if (token.reason) {
// Cancellation has already been requested
return;
}
token.reason = new Cancel(message);
resolvePromise(token.reason); // 调用resolvePromise,将会执行cancelToken实例上的`promise.then(fulfiled)`的成功回调函数
});
}
原理:
使用axios(config)
发送请求时,config.cancelToken
被设置为 实例cancelToken,所以在适配器adapter处理请求时,判断config.cancelToken存在,执行实例cancelToken中的promise,当resolvePromise被执行时,该promise的成功回调函数会被执行,在成功回调函数中,调用request.abort();
实现取消请求,取消后的请求,因为没有到达服务器,所以不会被响应拦截器拦截,但是可以使用全局的unhandledrejection事件监听到,或者用户自己的失败回调捕获到
在adapter,http和xhr中
if (config.cancelToken) {
// Handle cancellation
config.cancelToken.promise.then(function onCanceled(cancel) {
if (!request) {
return;
}
request.abort();
reject(cancel);
// Clean up request
request = null;
});
}
axios的创建过程
Axios
axios与Axios
axios严格来说不算是Axios的实例,axios是一个函数,且拥有Axios原型上的方法,和Axios实例上的属性;可以直接调用axios(config)发送请求,也可以axios.get(url, [,config]),axios.post(url, [,config])...发送请求(这是属于Axios原型上的方法,有被拷贝到axios上); Axios实例上的属性default和interceptors也被拷贝到axios中,所以可以通过axios.interceptors.response.use()添加拦截器