查看源码我们发现axios的几种请求方式都是调用request方法,下面一步步分析下。
Axios.prototype.request = function request(configOrUrl, config) { /*eslint no-param-reassign:0*/ // Allow for axios('example/url'[, config]) a la fetch API if (typeof configOrUrl === 'string') { //为了支持axios(url, {config})这种写法 config = config || {}; config.url = configOrUrl; } else { //axios(config) config = configOrUrl || {}; } //合并配置 config = mergeConfig(this.defaults, config); // 设置请求方法 默认get方法 if (config.method) { config.method = config.method.toLowerCase(); } else if (this.defaults.method) { config.method = this.defaults.method.toLowerCase(); } else { config.method = 'get'; } //数据类型转换 var transitional = config.transitional; if (transitional !== undefined) { validator.assertOptions(transitional, { silentJSONParsing: validators.transitional(validators.boolean), forcedJSONParsing: validators.transitional(validators.boolean), clarifyTimeoutError: validators.transitional(validators.boolean) }, false); } // 拦截器 var requestInterceptorChain = []; var synchronousRequestInterceptors = true; //遍历所有请求拦截器 this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) { // 对每一个请求拦截器执行以下代码 if (typeof interceptor.runWhen === 'function' && interceptor.runWhen(config) === false) { return; // 如果 runWhen 的结果是 false ,那么不执行这个拦截器 } // 判断异步同步 synchronousRequestInterceptors = synchronousRequestInterceptors && interceptor.synchronous; //头部添加, 先加入后执行 requestInterceptorChain.unshift(interceptor.fulfilled, interceptor.rejected); }); var responseInterceptorChain = []; this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) { // 先加入的先执行 responseInterceptorChain.push(interceptor.fulfilled, interceptor.rejected); }); var promise; // 如果拦截器是异步执行 if (!synchronousRequestInterceptors) { // 初始化一个执行链 var chain = [dispatchRequest, undefined]; // 把请求拦截器放在链首 Array.prototype.unshift.apply(chain, requestInterceptorChain); // 把响应拦截器放在链尾 chain = chain.concat(responseInterceptorChain); // 添加了拦截器后的chain数组大概会是这样的: // [ // requestFulfilledFn2, requestRejectedFn2,requestFulfilledFn1, requestRejectedFn1..., // dispatchRequest, undefined, // responseFulfilledFn1, responseRejectedFn1, responseFulfilledFn2, responseRejectedFn2...., // ] //初始化化一个promise,给个resolve状态 promise = Promise.resolve(config); while (chain.length) { promise = promise.then(chain.shift(), chain.shift()); } return promise; // 每次执行while循环,从chain数组里按序取出两项,并分别作为promise.then方法的第一个和第二个参数 // 按照我们使用InterceptorManager.prototype.use添加拦截器的规则,正好每次添加的就是我们通过InterceptorManager.prototype.use方法添加的成功和失败回调 // 第一个请求拦截器的fulfilled函数会接收到promise对象初始化时传入的config对象,而请求拦截器又规定用户写的fulfilled函数必须返回一个config对象,所以通过promise实现链式调用时,每个请求拦截器的fulfilled函数都会接收到一个config对象 // 第一个响应拦截器的fulfilled函数会接受到dispatchRequest请求到的数据(也就是response对象),而响应拦截器又规定用户写的fulfilled函数必须返回一个response对象,所以通过promise实现链式调用时,每个响应拦截器的fulfilled函数都会接收到一个response对象 //通过不断调用promise.then方法形成一个promise链,从而将所有的任务执行串联起来。 } //如果是同步 按照顺序 先指行请求拦截器 再执行 请求操作 请求结果后再执行 响应拦截器 var newConfig = config; while (requestInterceptorChain.length) { var onFulfilled = requestInterceptorChain.shift(); var onRejected = requestInterceptorChain.shift(); try { newConfig = onFulfilled(newConfig); } catch (error) { onRejected(error); break; } } try { promise = dispatchRequest(newConfig); } catch (error) { return Promise.reject(error); } while (responseInterceptorChain.length) { promise = promise.then(responseInterceptorChain.shift(), responseInterceptorChain.shift()); } return promise; };
手动添加几个请求拦截器和响应拦截器 可以更好的理解为什么axios 请求 是按照请求拦截 请求 响应拦截器顺序执行的。
axios.interceptors.request.use(function request1(config){ console.log("request1---success") return config },function requesterr1(config){ console.log("request1----error") return config }) axios.interceptors.request.use(function request2(config){ console.log("request2---success") return config },function requesterr2(config){ console.log("request2----error") return config }) axios.interceptors.response.use(function response1(response){ console.log("response1---success") return response },function responseerr1(response){ console.log("response1----error") return response }) axios.interceptors.response.use(function response2(response){ console.log("response2---success") return response },function responseerr2(response){ console.log("response2----error") return response })