axios是一个基于promise的http请求库,可用于浏览器和node。
const axios=require('axios')
axios.defaults.baseURL = 'http://xxx.com/api'
axios.interceptors.request.use(resolveFn1, rejectFn2)
axios.interceptors.response.use(resolveFn2, rejectFn2)
添加请求拦截器 添加响应拦截器
axios.get('/get').then(()=>{}, )
createInstance返回一个axios实例(axios.create也可以创建axios实例,
内部也是调用createInstance
createInstance
//./lib/axios.js
function createInstance(defaultConfig){
//根据默认设置 新建一个axios对象
var context=new Axios(defaultConfig)
//axios中所有的请求[axios,axios.get,axios.post等……]内部都是调用的
Axios.prototype.request,见[./code/Axios.js]
//将Axios.prototype.request的内部this绑定上新建的axios对象上
从而形成一个axios实例
var instance = bind(Axios.prototype.request, context)
utils.extend(instance, Axios.prototype, context)
将Axios.prototype属性添加到instance
content====》新建Axios对象
Axios.prototype.request(其内部this绑定到新建的Axios对象上)
[axios,axios.get,axios.post 都是调用Axios.prototype.request]
形成instance=axios实例
Axios.prototype属性添加
首先内部会新建一个Axios对象,Axios对象结构函数如下
function Axios(instanConfig){
this.defaults=instanceConfig 一些默认设置项
this.interceptors={
request: new InterceptorManager() //request拦截器
response: new InterceptorManager() //response拦截器
}
}
新建的axios对象主要用来挂载axios实例的一些设置(如defaults
会挂载axios实例的通用设置,interceptors用于存放拦截器)
axios实例是对axi内部的this绑定到新建的os.prototype.request方法包裹了一层函数,
主要是将axios。prototype。request内部的this绑定到新建的axios
通过utils.extend将内部context和Axios.prototype
最终的axios实例上面的内部的this指向的都是新建的axios对象
对每个axios实例设置不同config
因为axios内部调用的都是axios.prototype.request方法
axios.prototype.request默认请求方法为get。为了让开发者可以直接axios
(config)就可以发送get
}
Axios.prototype.request
见./lib/core/Axios
Axios.prototype.request=function request(config){
if(typeof config==='string'){
config=utils.merge({
url:arguments[0]
}, arguments[1]);
}
进行配置项的合并 优先级:Axios默认的defaults
config=utils.merge(defaults,{
method:'get'
}, this.defaults, config)
config.method=config.method.toLowerCase()
var chain=[dispatchRequest, undefined] //dispatchRequest封装了对于
发起ajax的逻辑处理
var promise=Promise.resolve(config)
var promise=Promise.resolve(config)
//request拦截器的执行顺序是:先加入后执行
this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor))
{
chain.unshift(interceptor.fulfilled,interceptor.rejected)
}}
//而response拦截器是:先加入的先执行
this.interceptors.response.forEach(function pushResponseInterceptors){
chain.push(interceptor.fulfilled,interceptor.rejected)
}
request.interceptor2=>request.interceptor1=>[dispatchRequest,undefined]=>
response.interceptor1=>response.interceptor2
内部通过promise.then形成promise链,从而将chain中拦截器的调用串联起来,
dispatchRequest是对ajax请求发起的封装实现,也会返还一个promise对象
while(chain.langth){
promise=promise.then(chain.shift(),chain.shift())
}
return promise
Axios.prototype.request内部会进行了一些配置项的合并工作
变量chain相当于一个任务队列
以2个为一组存放任务(1个是任务成功回调,1是任务失败回调,通过
不断调用promise.then方法形成一个promise链
执行顺序示例:
request.interceptor用于请求发起前的准备工作(可以修改data和headers
response.interceptor用于服务器返回数据后的处理工作(也是对data处理,
整个请求的发起过程通过dispatchRequest实现的
dispatchRequest
function dispatchRequest(config){
依次调用transformRequest数组中的函数对data、headers进行处理,
方便在向服务器发送请求之前对data和headers进行修改(例如对data
进行编码加密等
config.data=transformData(
config.data,
config.headers,
config.transformRequest
);
return adapter(config).then(
function onAdaptRequest(response)
)
}
*/
/*
1.
vue不支持发送ajax请求,要用vue-resource(1.0)\axios(2.0)
跨域:
vue-resource:
this.$http.get\head\delete\jsonp(url,[options])
this.$http.post\put\patch(url,[body],[options])
axios不支持跨域,第三方
2.axios基于promise的用于浏览器和nodejs的http请求客户端,本质上也是对原生XHR的封装
原理:
axios(const axios=require('axios'))来自createInstance,
(顾名思义,创建实例, return instance;),
内部新建一个Axios对象,
axios/axios.get/axios.post……都来自Axios.prototype.request
用bind把Axios.prototype.request内部this绑定到Axios对象上,形成
一个axios实例
然后返回这个instance
3.为什么不将所有方法在Axios上实现然后返回new Axios呢?
Axios.prototype.request默认请求方法为get。
为了可以直接axios(config)就可以发送get请求,而不需要axios.get(config)
4.Axios.prototype.request
(我知道)内部有配置项的合并,dispatchRequest封装了发起ajax(整个请求过程的发起过程)
(还有)request拦截器(先加入后执行,用于请求发起前的准备工作) 和
response拦截器(先加入的先执行,用于服务器返回数据之后的处理工作),
5.dispatchRequest
transformData(config.data, config.headers, config.transformRequest)是为了向服务器发送请前对 data 进行处理
return adapter(适配器模式,对不同环境做了适配处理,根据config发送请求然后返回一个promise,promise的状态根据请求的结果来决定)