Preface这应该是最常用的一个请求库了,因为它可以支持多种配置,跨平台实现,链式调用返回promise。完整地浏览源代码可以提高您对请求库的理解。axios源码系列(一)---目录结构及工具功能axios源码系列(二)---适配器内部axios源码系列(三)---默认配置和取消请求axios源码系列(四)---axiosanddispatchRequestandinterceptordefault配置axios/lib/defaults.js,axios库的默认参数配置varutils=require('./utils');varnormalizeHeaderName=require('./helpers/normalizeHeaderName');varDEFAULT_CONTENT_TYPE={'Content-Type':'application/x-www-form-urlencoded'};functionsetContentTypeIfUnset(headers,value){if(!utils.isUndefined(headers)&&utils.isUndefined(headers['Content-Type'])){headers['Content-Type']=value;}}functiongetDefaultAdapter(){变种适配器;if(typeofXMLHttpRequest!=='undefined'){//对于浏览器使用XHR适配器adapter=require('./adapters/xhr');}elseif(typeofprocess!=='undefined'&&Object.prototype.toString.call(process)==='[objectprocess]'){//对于节点使用HTTP适配器adapter=require('./adapters/HTTP');}返回adapter;}这里只有四个东西:工具库的介绍和解析头文件名的函数。将默认的Content-Type设置为浏览器的默认编码格式。设置与标头中的空值相对应的Content-Type值的定义。根据宿主环境获取相应适配器中的解析头名称函数源码如下:axios/lib/helpers/normalizeHeaderName.js过滤查找是否存在大小写不同的等价请求头,如果是的,设置一个新的请求头并删除旧的请求头varutils=require('../utils');module.exports=functionnormalizeHeaderName(headers,normalizedName){utils.forEach(headers,functionprocessHeader(value,name){if(name!==normalizedName&&name.toUpperCase()===normalizedName.toUpperCase()){headers[normalizedName]=value;deleteheaders[name];}});};这是暴露的对象normalizeHeaderName(headers,'Content-Type');如果(utils.isFormData(数据)||utils.isArrayBuffer(数据)||utils.isBuffer(数据)||utils.isStream(数据)||utils.isFile(数据)||utils.isBlob(数据)){返回数据;}如果(utils.isArrayBufferView(data)){返回data.buffer;}if(utils.isURLSearchParams(data)){setContentTypeIfUnset(headers,'application/x-www-form-urlencoded;charset=utf-8');返回数据.toString();}if(utils.isObject(data)){setContentTypeIfUnset(headers,'application/json;charset=utf-8');返回JSON.stringify(数据);}返回数据;}],transformResponse:[functiontransformResponse(data){/*eslintno-param-reassign:0*/if(typeofdata==='string'){try{data=JSON.parse(data);}}catch(e){/*忽略*/}}返回数据;}],/***中止请求的超时时间(以毫秒为单位)。如果设置为0(默认),则不会创建*超时。*/timeout:0,xsrfCookieName:'XSRF-TOKEN',xsrfHeaderName:'X-XSRF-TOKEN',maxContentLength:-1,validateStatus:functionvalidateStatus(status){返回状态>=200&&状态<300;}};defaults.headers={common:{'Accept':'application/json,text/plain,*/*'}};utils.forEach(['delete','get','head'],functionforEachMethodNoData(method){defaults.headers[method]={};});utils.forEach(['post','put','patch'],functionforEachMethodWithData(method){defaults.headers[method]=utils.merge(DEFAULT_CONTENT_TYPE);});module.exports=默认值;主要提供了几种默认的配置配置来配置适配器宿主环境对应的适配器。transformRequest内置的转换函数根据相应的格式设置请求transformResponse的内置转换函数。时间xsrfCookieName用作xsrf令牌值的cookie的名称xsrfHeaderName承载xsrf令牌值的HTTP标头的名称maxContentLength定义允许的响应内容的最大大小默认请求标头['delete','get','head']定义相关请求方法的默认请求头{}[post','put','patch']定义相关请求方法的默认请求头,{'Content-Type':'application/x-www-form-urlencoded'}取消请求axios/lib/cancel/Cancel.js/***`Cancel`是在取消操作时抛出的对象。**@class*@param{string=}message消息。*/函数取消(我ssage){this.message=message;}Cancel.prototype.toString=functiontoString(){return'Cancel'+(this.message?':'+this.message:'');};Cancel.prototype.__CANCEL__=true;module.exports=Cancel;创建Cancel的构造函数,表示取消某个请求,提供一句取消消息和标记axios/lib/cancel/CancelToken.jsvarCancel=require('./Cancel');/***`CancelToken`是可用于请求取消操作的对象。**@class*@param{Function}executor执行器函数。*/functionCancelToken(executor){if(typeofexecutor!=='function'){thrownewTypeError('executor必须是一个函数。');}varresolvePromise;this.promise=newPromise(functionpromiseExecutor(resolve){resolvePromise=resolve;});var令牌=这个;executor(functioncancel(message){if(token.reason){//已经请求取消return;}token.reason=newCancel(message);resolvePromise(token.reason);});}/***抛出一个`Cancel`如果已请求取消。*/CancelToken.prototype.throwIfRequested=functionthrowIfRequested(){if(this.reason){throwthis.reason;}};/***返回一个对象,该对象包含一个新的`CancelToken`和一个函数,该函数在调用时*取消`CancelToken`。*/CancelToken.source=functionsource(){varcancel;vartoken=newCancelToken(functionexecutor(c){cancel=c;});return{token:token,cancel:cancel};};module.exports=CancelToken;创建一个CancelToken对象来取消请求的操作:定义一个新的Promise,将状态改变的触发时机传递给外部执行回调函数参数if它已经包含了reason属性,表示发出取消请求的操作将中断操作;否则,创建一个新的Cancel对象并更改Promise状态以返回该对象。原型绑定到throwIfRequested方法。如果实例已经被取消,则可以直接抛出取消信息。源方法绑定到构造函数并调用然后你可以返回一个新的CancelToken实例和取消方法axios/lib/cancel/isCancel.jsmodule.exports=functionisCancel(value){return!!(value&&value.__CANCEL__);};通过你是否拥有__CANCEL__属性获得知道一个请求是否已经被取消。例子constCancelToken=axios.CancelToken;constsource=CancelToken.source();axios.get('/user/12345',{取消elToken:source.token}).catch(function(thrown){if(axios.isCancel(thrown)){console.log('Requestcanceled',thrown.message);}else{//处理错误}});axios.post('/user/12345',{name:'newname'},{cancelToken:source.token})//取消请求(message参数可选)source.cancel('操作被用户取消.');或者constCancelToken=axios.CancelToken;letcancel;axios.get('/user/12345',{cancelToken:newCancelToken(functionexecutor(c){//执行器函数接收一个取消函数作为参数cancel=c;})});//取消requestcancel();
