You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
// axios 和 instance 都会调用createInstancefunctioncreateInstance(defaultConfig){varcontext=newAxios(defaultConfig);// 绑定Axios原型上的方法request// Axios.prototype.request.bind(context), 返回的是方法。varinstance=bind(Axios.prototype.request,context);// 将Axios上原型的方法复制到instance上,使得axios能调用get,post,put,delete等方法 axios.get()utils.extend(instance,Axios.prototype,context);// Copy context to instanceutils.extend(instance,context);returninstance;}// Create the default instance to be exportedvaraxios=createInstance(defaults);// Expose Axios class to allow class inheritanceaxios.Axios=Axios;// 同样支持axios.create(),创建instance,跟axios没有太大区别,都是通过调用createInstance来的,但是instance没有axios后面添加的cancel,cancelToken等方法axios.create=functioncreate(instanceConfig){returncreateInstance(mergeConfig(axios.defaults,instanceConfig));};// 为axios添加新的属性方法,取消请求。axios.Cancel=require('./cancel/Cancel');axios.CancelToken=require('./cancel/CancelToken');axios.isCancel=require('./cancel/isCancel');
// ajax请求,http请求functiongetDefaultAdapter(){varadapter;if(typeofXMLHttpRequest!=='undefined'){// For browsers use XHR adapteradapter=require('./adapters/xhr');}elseif(typeofprocess!=='undefined'&&Object.prototype.toString.call(process)==='[object process]'){// For node use HTTP adapteradapter=require('./adapters/http');}returnadapter;}
4 xhr
module.exports=functionxhrAdapter(config){returnnewPromise(functiondispatchXhrRequest(resolve,reject){varrequestData=config.data;varrequestHeaders=config.headers;if(utils.isFormData(requestData)){deleterequestHeaders['Content-Type'];// Let the browser set it}varrequest=newXMLHttpRequest();// HTTP basic authenticationif(config.auth){varusername=config.auth.username||'';varpassword=config.auth.password ? unescape(encodeURIComponent(config.auth.password)) : '';requestHeaders.Authorization='Basic '+btoa(username+':'+password);}// 合并请求连接,可以通过{baseURL: 'xxx'}或者axios.defaults.baseURL = 'https://xxx';设置varfullPath=buildFullPath(config.baseURL,config.url);request.open(config.method.toUpperCase(),buildURL(fullPath,config.params,config.paramsSerializer),true);// Set the request timeout in MSrequest.timeout=config.timeout;// Listen for ready state// // onreadystatechange的状态码// 0: 初始化, XMLHttpRequest对象还没有完成初始化// 1: 载入, XMLHttpRequest对象开始发送请求// 2: 载入完成, XMLHttpRequest对象的请求发送完成// 3: 解析, XMLHttpRequest对象开始读取服务器的响应// 4: 完成, XMLHttpRequest对象读取服务器响应结束request.onreadystatechange=functionhandleLoad(){if(!request||request.readyState!==4){return;}// The request errored out and we didn't get a response, this will be// handled by onerror instead// With one exception: request that using file: protocol, most browsers// will return status as 0 even though it's a successful requestif(request.status===0&&!(request.responseURL&&request.responseURL.indexOf('file:')===0)){return;}// Prepare the responsevarresponseHeaders='getAllResponseHeaders'inrequest ? parseHeaders(request.getAllResponseHeaders()) : null;varresponseData=!config.responseType||config.responseType==='text' ? request.responseText : request.response;varresponse={data: responseData,status: request.status,statusText: request.statusText,headers: responseHeaders,config: config,request: request};// 当返回的status状态码在[200, 300)之间,返回resolve(response)//default.js中 validateStatus: function validateStatus(status) {// return status >= 200 && status < 300;// }settle(resolve,reject,response);// Clean up requestrequest=null;};// Handle browser request cancellation (as opposed to a manual cancellation)// 取消请求request.onabort=functionhandleAbort(){if(!request){return;}reject(createError('Request aborted',config,'ECONNABORTED',request));// Clean up requestrequest=null;};// 处理网络错误问题request.onerror=functionhandleError(){// Real errors are hidden from us by the browser// onerror should only fire if it's a network errorreject(createError('Network Error',config,null,request));// Clean up requestrequest=null;};// 处理请求超时问题。request.ontimeout=functionhandleTimeout(){vartimeoutErrorMessage='timeout of '+config.timeout+'ms exceeded';if(config.timeoutErrorMessage){timeoutErrorMessage=config.timeoutErrorMessage;}reject(createError(timeoutErrorMessage,config,'ECONNABORTED',request));// Clean up requestrequest=null;};// Add xsrf header// This is only done if running in a standard browser environment.// Specifically not if we're in a web worker, or react-native.// 浏览器if(utils.isStandardBrowserEnv()){// Add xsrf headervarxsrfValue=(config.withCredentials||isURLSameOrigin(fullPath))&&config.xsrfCookieName ?
cookies.read(config.xsrfCookieName) :
undefined;if(xsrfValue){requestHeaders[config.xsrfHeaderName]=xsrfValue;}}// Add headers to the requestif('setRequestHeader'inrequest){utils.forEach(requestHeaders,functionsetRequestHeader(val,key){if(typeofrequestData==='undefined'&&key.toLowerCase()==='content-type'){// Remove Content-Type if data is undefineddeleterequestHeaders[key];}else{// Otherwise add header to the requestrequest.setRequestHeader(key,val);}});}// Add withCredentials to request if neededif(!utils.isUndefined(config.withCredentials)){request.withCredentials=!!config.withCredentials;}// Add responseType to request if neededif(config.responseType){try{request.responseType=config.responseType;}catch(e){// Expected DOMException thrown by browsers not compatible XMLHttpRequest Level 2.// But, this can be suppressed for 'json' type as it can be parsed by default 'transformResponse' function.if(config.responseType!=='json'){throwe;}}}// Handle progress if neededif(typeofconfig.onDownloadProgress==='function'){request.addEventListener('progress',config.onDownloadProgress);}// Not all browsers support upload eventsif(typeofconfig.onUploadProgress==='function'&&request.upload){request.upload.addEventListener('progress',config.onUploadProgress);}// 取消请求。if(config.cancelToken){// Handle cancellationconfig.cancelToken.promise.then(functiononCanceled(cancel){if(!request){return;}request.abort();reject(cancel);// Clean up requestrequest=null;});}if(!requestData){requestData=null;}// Send the requestrequest.send(requestData);});};
functionCancelToken(executor){if(typeofexecutor!=='function'){thrownewTypeError('executor must be a function.');}varresolvePromise;// 创建了内置的promise对象,将resovle控制放在executor中去控制//eg: let resolveHandle;// new Promise((resolve) => {// resolveHandle = resolve;// }).then((val) => {// console.log('resolve', val);// });// resolveHandle('ok');this.promise=newPromise(functionpromiseExecutor(resolve){resolvePromise=resolve;});vartoken=this;executor(functioncancel(message){if(token.reason){// Cancellation has already been requestedreturn;}token.reason=newCancel(message);resolvePromise(token.reason);});}
axios源码分析
源码目录分析
axios的工作流程
axios的工作原理
1. axios
还是
instance`都会调用`createInstance`函数,构造`Axios`的实例,但`axios`从本质上来说还是一个函数,通过`extend,bind`将`Axios`上复制所有的原型扩展方法。axios
和instance
是有区别的,axios
包含了后面扩展的Cancel
、CancelToken
等方法。createInstance
返回的axios
函数的属性上,就已经挂在了Axios
原型上的方法和属性了。2. Axios 核心类
unshift
插入,倒序执行,返回拦截是push
插入,顺序执行。request
做了哪些事,支持config
是个字符串,表现形式为axios('/xxx')
, 也可以是object
, 会去合并mergeConfig(this.defaults, config)
默认值。toLowerCase
, 默认为get
方式interceptors
存放的方法chain.length
不为0
, 支持链式调用,最终返回promise
3 dispatchRequest
dispatchRequest
主要做了哪些,将data、headers
放入到transformData
中执行,再将headers
扁平化处理transformRequest
函数数组,对data
数据进行转换adapter
判断出是node
坏境还是浏览器环境,adapter.then()
, 将返回response
数据。4 xhr
创建
new XMLHttpRequest()
实例合并请求连接,可以通过{baseURL: 'xxx'}或者axios.defaults.baseURL = 'https://xxx';设置
监听
onreadystatechange
变化,0: 初始化, XMLHttpRequest对象还没有完成初始化
1: 载入, XMLHttpRequest对象开始发送请求
2: 载入完成, XMLHttpRequest对象的请求发送完成
3: 解析, XMLHttpRequest对象开始读取服务器的响应
4: 完成, XMLHttpRequest对象读取服务器响应结束
收集
response
返回数据,执行settle
函数,调用validateStatus(status)
判断是否在[200, 300)
,成功状态后resolve(response)
返回数据。结合代码
5 取消请求
cancelToken
主要做了什么事情,内置创建了promise
对象,通过resolvePromise=resolve
,将控制放在executor
中去控制,config.cancelToken.promise.then
在异步中去取消请求cancelToken
只会对未进行相应的请求进行取消,已响应的请求执行了也不会有什么作用。总结
axios
是一个基于promise
的Http
库,在浏览器环境使用XHR
,在node
环境中使用http
模块发送请求,在axios
,可以对请求,返回进行拦截,支持链式拦截,请求拦截为倒序拦截,使用unshift
往前插入数据,返回拦截使用push
方法,正常拦截。取消请求的是一个异步分离的设计方案,利用
promise
的异步效果,通过切换promise
的状态,从而达到异步取消请求的实现。axios
和axios.create
的差别是增加了cancelToken
等方法。The text was updated successfully, but these errors were encountered: