为了方便,axios对象可以作为对象和函数。axios.post('/user',{firstName:'Fred',lastName:'Flintstone'}).then(function(response){console.log(response);}).catch(function(error){console.日志(错误);});axios({method:'post',url:'/user/12345',data:{firstName:'Fred',lastName:'Flintstone'}});axios是怎么做到的,可以看到instance其实就是一个绑定this的函数,调用axios就是调用context.requestfunctioncreateInstance(){//可以作为函数使用的Secretvarinstance=bind(Axios.prototype.request,语境);//可以用作对象的Secretutils.extend(instance,Axios.prototype,context);//获取结构体函数继承的属性utils.extend(instance,context);返回实例}varaxios=createInstance(defaults);接下来,让我们看一下请求方法。所有HTTP请求都会调用Axios.prototype.request。这个功能可以认为是整个axios的骨架,非常重要。axios.prototype.request=functionrequest(config){//每个请求都会重新组合一个config,所以通过操作config对象,可以识别请求并进行一些操作。其实每个axios拦截器都可以获取到config对象config=utils.merge(defaults,this.defaults,{method:'get'},config);//挂载拦截器的主要逻辑varchain=[dispatchRequest,undefined];varpromise=Promise.resolve(config);this.interceptors.request.forEach(functionunshiftRequestInterceptors(interceptor){chain.unshift(interceptor.fulfilled,interceptor.rejected);});this.interceptors.response.forEach(functionpushResponseInterceptors(interceptor){chain.push(interceptor.fulfilled,interceptor.rejected);});while(chain.length){promise=promise.then(chain.shift(),chain.shift());}returnpromise;}从拦截器的主要逻辑,我们可以得到以下几点:发送请求的整个执行顺序是,requestInterceptors——“dispatchRequest——”responseInterceptors拦截器最初接收到的对象是config,它是在axios的使用中也规定了请求的拦截器必须返回config,这也是为什么每个请求拦截器的函数参数都是config。拦截器的执行顺序和interceptors.request.use(function(){/*...*/})的执行顺序一样off,即先使用的请求拦截器会先执行。如果拦截器中的函数是async函数,会阻塞整个拦截器链的执行,而transformData不会,所以如果需要对请求的数据做异步处理,必须在拦截器中完成。看下,不同的http方法是怎么复用request方法的utils.forEach(['delete','get','head','options'],functionforEachMethodNoData(method){/*eslintfunc-names:0*/Axios.prototype[method]=function(url,config){returnthis.request(utils.merge(config||{},{method:method,url:url}));};});utils。forEach(['post','put','patch'],functionforEachMethodWithData(method){/*eslintfunc-names:0*/Axios.prototype[method]=function(url,data,config){返回这个.request(utils.merge(config||{},{method:method,url:url,data:data}));};});接下来我们看dispatchRequest的核心总辑://处理config...var适配器=config.adapter||defaults.adapter;returnadapter(config).then(functiononAdapterResolution(response){throwIfCancellationRequested(config);//转换响应dataresponse.data=transformData(response.data,response.headers,config.transformResponse);returnresponse;},函数onAdapterRejection(reason){if(!isCancel(原因)){throwIfCancellationRequested(配置);//转换响应数据if(reason&&reason.response){reason.response.data=transformData(reason.response.data,reason.response.headers,config.transformResponse);}}returnPromise.reject(原因);});可以看到dispatchRequest的核心逻辑大概有三步处理config和使用adapter发送请求。axios默认内置了两个adapter,一个负责在brower中发送请求,一个负责在node端发送请求时,在根文件的defaults下可以看到构造好的响应数据.所以通过阅读dispatchRequest方法,我们可以得到如下启示:adapter是可以替换的,所以如果你觉得你的xhr或者http逻辑更适合业务的需要可以完全替换掉,你也可以开发第三个adapter来处理特定情况,例如开发处理缓存的适配器。其实我现在的项目就是这样做的。响应拦截器接收响应Object至此,我们就把axios的核心逻辑读完了,从中也可以看出axios是非常易用和可扩展的。尤其是可扩展性,从发送请求到接收响应的过程几乎所有部分都是可扩展的,尤其是config、adapter、interceptor留有很大的想象空间。
