1. axios的构造过程 代码实现如下:
// 创建一个Axios构造函数
function Axios(config){
this.default = config
this.intercepters = {
request:{},
response: {}
}
}
// 原型上添加方法
Axios.prototype.request = function(config){
console.log('发送ajax请求的方法 request', config);
}
Axios.prototype.get = function(config){
console.log('发送ajax请求的方法 get', config);
return this.request({method: 'get'})
}
Axios.prototype.post = function(config){
console.log('发送ajax请求的方法 get', config);
return this.request({method: 'post'})
}
// 声明函数
function createInstance(config){
//实例化对象 context.get()
let context = new Axios(config)
// 请求函数
let instance = Axios.prototype.request.bind(context)
// 将Axios.prototype的方法添加到instance函数对象中
Object.keys(Axios.prototype).forEach(key=>{
// console.log('遍历', key);
instance[key] = Axios.prototype[key].bind(context)
})
// 将Axios.default与intercepters添加到instance函数对象中
Object.keys(context).forEach(key=>{
// console.log('遍历', key);
instance[key] = context[key]
})
return instance
}
let axios = createInstance()
// 当对象去使用
axios({method: 'post', url:'http://localhost:3000/posts'})
// 当函数去使用
axios.get({})
2. axios如何发送请求,代码实现如下:
// 1,声明构造函数
function Axios(config){
this.config = config
}
// 发送请求
Axios.prototype.request = function(config){
//1,创建一个promise对象
let promise = Promise.resolve(config)
// console.log('发送ajax请求的方法 request', promise);
//2,声明一个数组
let chains = [dispatchRequest, undefined]
//3,调用then方法指定回调
let result = promise.then(chains[0],chains[1])
//4,返回promise对象
return result
}
//2,dispatchRequest函数
function dispatchRequest(config){
return xhrAdapter(config).then(res=>{
console.log('dispatchRequest res', res);
// 对响应成功的结果进行转化处理
return res
}, err=>{
console.log('dispatchRequest err', err);
throw new Error(err)
})
}
// 3,adaptor适配器
function xhrAdapter(config){
return new Promise((resolve, reject)=>{
// 创建ajax请求
let xhr = new XMLHttpRequest()
let {methord, url, data} = config || {}
xhr.open(methord, url, true)
xhr.send(data)
// 判断成功的状态并进行处理
xhr.onreadystatechange = function (){
if(xhr.readyState == 4){
if(xhr.status>=200 && xhr.status <300){
// 调用成功
resolve({
config: config,
data: JSON.parse(xhr.response),
headers:xhr.getAllResponseHeaders(),
request: xhr,
status:xhr.status,
statusText:xhr.statusText
})
}else{
// 调用失败
reject(new Error('xhrAdapter 调用失败'))
}
}
}
})
}
// 4, 创建ajax函数
let axios = Axios.prototype.request.bind(null)
// 当对象去使用 示例
axios({methord: 'get', url:'http://localhost:3000/posts', data:{}}).then(res=>{
console.log(res);
})
3. axios拦截器及其实现原理 代码如下:
// 构造函数
function Axios(config){
this.config = config
this.interceptors = {
request: new InterceptorManager(),
response: new InterceptorManager(),
}
}
// 请求方法(重点!)
Axios.prototype.request = function(config){
// 创建一个promise对象
let promise = Promise.resolve(config)
// 创建一个chain数组
// undefined是用来跳失败的renject,的结果的
const chains = [dispatchRequest, undefined]
// 处理拦截器
// 请求拦截器:将请求拦截器的回调 压入到 chain 的前面 reques.handles = []
// console.log(this.interceptors.request.handlers);
this.interceptors.request.handlers.forEach(item=>{
chains.unshift(item.fulfilled, item.rejected)
})
this.interceptors.response.handlers.forEach(item=>{
chains.push(item.fulfilled, item.rejected)
})
console.log(chains);
// 遍历数组
while (chains.length >0) {
// 从数组当中取出回调 通过promise链条的方式进行执行回调
promise = promise.then(chains.shift(), chains.shift())
}
return promise
}
function dispatchRequest(config){
// 返回一个promise队列
return new Promise((resolve, reject)=>{
resolve({
status:'200',
statusText: '请求成功'
})
})
}
// 创建实例
let context = new Axios({})
// 创建axios函数
let axios = Axios.prototype.request.bind(context)
// 将context属性的config、interceptors添加到实例axios上
Object.keys(context).forEach(key => {
axios[key] = context[key]
});
// 拦截器的构造函数实现
function InterceptorManager(){
this.handlers = []
}
// use方法
InterceptorManager.prototype.use = function(fulfilled, rejected){
this.handlers.push({
fulfilled,
rejected
})
}
// 请求拦截器 使用unshift推入一号到chains数组前
// use在执行的时候把回调保存在request的handle身上,通过foreach函数进行chain遍历
axios.interceptors.request.use(function one(config){
console.log('请求拦截器成功 1号');
return config
}, function one(err){
console.log('请求拦截器失败 1号', err);
return Promise.reject(err)
})
axios.interceptors.request.use(function two(config){
console.log('请求拦截器成功 2号');
return config
}, function one(err){
console.log('请求拦截器失败 2号', err);
return Promise.reject(err)
})
// 响应拦截器 使用push将handle添加到chains数组后面
// promise = promise.then(responseInterceptorChain.shift(), responseInterceptorChain.shift())
axios.interceptors.response.use(function one(response){
console.log('响应拦截器成功 1号');
return response
}, function one(err){
console.log('响应拦截器失败 1号', err);
return Promise.reject(err)
})
axios.interceptors.response.use(function two(response){
console.log('响应拦截器成功 2号');
return response
}, function one(err){
console.log('响应拦截器失败 2号', err);
return Promise.reject(err)
})
// 打印结果是:
// 请求拦截器2号 请求拦截器1号 响应拦截器1号 响应拦截器2号
// 当对象去使用 示例
axios({methord: 'post', url:'http://localhost:3000/posts',}).then(res=>{
console.log('res', res);
})
4. axios如何取消请求
// -------axios取消请求html---------
// 构造函数
function Axios(config){
this.config = config
}
// 原型的request方法
Axios.prototype.request = function(config){
return dispatchRequest(config)
}
// dispatchRequest函数
function dispatchRequest(config){
return xhrAdapter(config)
}
// 实际创建ajax请求的函数
function xhrAdapter(config){
return new Promise((resolve, reject)=>{
// 创建ajax请求
let xhr = new XMLHttpRequest()
let {methord, url, data} = config || {}
xhr.open(methord, url, true)
xhr.send(data)
// 判断成功的状态并进行处理
xhr.onreadystatechange = function (){
if(xhr.readyState == 4){
if(xhr.status>=200 && xhr.status <300){
// 调用成功
resolve({
config: config,
data: JSON.parse(xhr.response),
headers:xhr.getAllResponseHeaders(),
request: xhr,
status:xhr.status,
statusText:xhr.statusText
})
}else{
// 调用失败
reject(new Error('xhrAdapter 调用失败'))
}
}
}
// 处理cancelToken中的取消请求,核心是xhr.abort()
if(config.cancelToken){
//对cancelToken对象身上的promise对象,指定了成功的回调,从而结束掉请求的promise状态
config.cancelToken.promise.then(val=>{
console.log('用户主动取消了请求');
//取消XMLHttpRequest链接
xhr.abort()
})
}
})
}
// 创建实例
let context = new Axios({})
// 创建axios函数
let axios = Axios.prototype.request.bind(context)
// 将context属性的config、interceptors添加到实例axios上
Object.keys(context).forEach(key => {
axios[key] = context[key]
});
// 取消请求的构造函数
function cancelToken(executor){
// 声明一个变量
let resolvePromise
// 为实例对象添加属性
this.promise = new Promise((resolve, reject)=>{
resolvePromise = resolve
})
// 调用executor函数
executor(function(){
// 执行resolvePromise方法
resolvePromise()
})
}
// ------ 以下为功能测试代码 -------
let cancel = null
let myCancel = new cancelToken(
function(c){
cancel = c
}
)
// 当对象去使用 示例
axios({methord: 'get', url:'http://localhost:3000/comments', cancelToken:myCancel}).then(res=>{
console.log('res', res);
cancel = null
})
5.自行封装一个完整的axios库
// ----------------axios完整模拟实现----------------
// 构造函数
function Axios(config){
this.config = config
this.interceptors = {
request: new InterceptorManager(),
response: new InterceptorManager(),
}
}
// 原型的request方法(重难点)
Axios.prototype.request = function(config){
// 创建一个promise对象
let promise = Promise.resolve(config)
// 创建一个chain数组 undefined是用来跳失败的renject,的结果的
// let chains = [dispatchRequest(config), undefined]
const chains = [dispatchRequest, undefined]
// ---处理拦截器---
// 请求拦截器:将请求拦截器的回调 压入到 chain 的前面 request.handles = []
// 作用:可以对(config)请求进行检查或配置进行特殊处理,如设置请求头
this.interceptors.request.handlers.forEach(item=>{
chains.unshift(item.fulfilled, item.rejected)
})
// 响应拦截器:将响拦截器的回调 push到 chain 的队列后 response.handles = []
// 作用:对响应的数据(data)进行特殊处理,如解析字符串
this.interceptors.response.handlers.forEach(item=>{
chains.push(item.fulfilled, item.rejected)
})
// 遍历数组
while (chains.length >0) {
// 从数组当中取出回调 通过promise链条的方式进行执行回调
promise = promise.then(chains.shift(), chains.shift())
}
// 返回这个promise
return promise
}
// dispatchRequest函数
function dispatchRequest(config){
// 返回一个promise队列
return xhrAdapter(config).then(res=>{
// 对响应成功的结果进行一些转化处理
return res
}, err=>{
// console.log('dispatchRequest err', err);
throw new Error(err)
})
}
// 实际创建ajax请求的函数
function xhrAdapter(config){
// 返回一个promise队列
return new Promise((resolve, reject)=>{
// 创建ajax请求
let xhr = new XMLHttpRequest()
let {methord, url, data} = config || {}
xhr.open(methord, url, true)
xhr.send(data)
// 1. 处理cancelToken中的取消请求,核心是xhr.abort()
// 2. config.cancelToken.promise对象当前的状态是fulfilled
if(config && config.cancelToken){
//对cancelToken对象身上的promise对象,指定了成功的回调,从而结束掉请求的promise状态
config.cancelToken.promise.then(val=>{
console.log('用户主动取消了请求!');
//取消XMLHttpRequest链接
xhr.abort()
})
}
// 判断成功的状态并进行处理
xhr.onreadystatechange = function (){
if(xhr.readyState == 4){
if(xhr.status>=200 && xhr.status <300){
// 调用成功
console.log('xhrAdapter 调用成功');
resolve({
config: config,
data: JSON.parse(xhr.response),
headers:xhr.getAllResponseHeaders(),
request: xhr,
status:xhr.status,
statusText:xhr.statusText
})
}else{
// 调用失败
reject(new Error('xhrAdapter 调用失败'))
}
}
}
})
}
// // 创建实例
let context = new Axios({})
// // 创建axios函数
let axios = Axios.prototype.request.bind(context)
// 将context属性的config、interceptors添加到实例axios上
Object.keys(context).forEach(key => {
axios[key] = context[key]
});
// 拦截器的构造函数实现
function InterceptorManager(){
this.handlers = []
}
// use方法
InterceptorManager.prototype.use = function(fulfilled, rejected){
this.handlers.push({
fulfilled,
rejected
})
}
// 取消请求的构造函数
function cancelToken(executor){
// 声明一个变量
let resolvePromise
// 为实例对象添加属性
this.promise = new Promise((resolve, reject)=>{
resolvePromise = resolve()
})
// 调用executor函数
executor(function(){
// 执行resolvePromise方法
resolvePromise()
})
}
// ------ 功能测试代码 --------
// 拦截器相关
axios.interceptors.request.use(function one(config){
console.log('请求拦截器成功 1号');
return config
}, function one(err){
console.log('请求拦截器失败 1号', err);
return Promise.reject(err)
})
axios.interceptors.response.use(function one(response){
console.log('响应拦截器成功 1号');
return response
}, function one(err){
console.log('响应拦截器失败 1号', err);
return Promise.reject(err)
})
// 取消请求相关
let cancel = null
let myCancel = new cancelToken(
function(c){
cancel = c
}
)
if(cancel !== 'null'){
cancel = null
}
// 当对象去使用 示例,是否主动取消请求:cancelToken:myCancel
axios({methord: 'get', url:'http://localhost:3000/comments', cancelToken:''}).then(res=>{
console.log('axios res: ', res);
cancel = null
})