当前位置: 首页>后端>正文

如何模拟实现一个发送请求的axios库?

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
})

https://www.xamrdz.com/backend/3e31936012.html

相关文章: