Skip to content

基于 xhr 实现 axios

上面我们讲到二次封装 axios ,但是现在我们尝试完全脱离 axios,自己实现一个 axios,由于 axios 底层是基于 xhr 做了二次封装,所以我们也可以尝试一下。

xhr 二次封装

src/plugins/xhr.js

javascript
/**
 * 请求拦截器队列
 * 响应拦截器队列
 */
const request = []
const response = []

/**
 * xhr 封装
 */
function axios(config) {
    return new Promise((resolve) => {
        request.forEach((fn) => (config = fn(config)))

        const { method, url, data, headers } = config

        /**
         * 新建请求
         */
        const xhr = new XMLHttpRequest()
        xhr.open(method, url)

        /**
         * 设置请求头
         */
        for (const key in headers) {
            xhr.setRequestHeader(key, headers[key])
        }

        /**
         * 发送请求
         */
        xhr.send(data)

        /**
         * 监听返回值
         */
        xhr.onreadystatechange = () => {
            if (!(xhr.readyState === 4 && xhr.status === 200)) return

            let data = JSON.parse(xhr.responseText)

            response.forEach((fn) => (data = fn(data)))

            resolve(data)
        }
    })
}

/**
 * 拦截器定义
 */
axios.interceptors = {
    request: {
        use: (fn) => {
            request.push(fn)
        }
    },
    response: {
        use: (fn) => {
            response.push(fn)
        }
    }
}

export default axios
/**
 * 请求拦截器队列
 * 响应拦截器队列
 */
const request = []
const response = []

/**
 * xhr 封装
 */
function axios(config) {
    return new Promise((resolve) => {
        request.forEach((fn) => (config = fn(config)))

        const { method, url, data, headers } = config

        /**
         * 新建请求
         */
        const xhr = new XMLHttpRequest()
        xhr.open(method, url)

        /**
         * 设置请求头
         */
        for (const key in headers) {
            xhr.setRequestHeader(key, headers[key])
        }

        /**
         * 发送请求
         */
        xhr.send(data)

        /**
         * 监听返回值
         */
        xhr.onreadystatechange = () => {
            if (!(xhr.readyState === 4 && xhr.status === 200)) return

            let data = JSON.parse(xhr.responseText)

            response.forEach((fn) => (data = fn(data)))

            resolve(data)
        }
    })
}

/**
 * 拦截器定义
 */
axios.interceptors = {
    request: {
        use: (fn) => {
            request.push(fn)
        }
    },
    response: {
        use: (fn) => {
            response.push(fn)
        }
    }
}

export default axios

axios 二次封装

src/plugins/axios.js

javascript
import axios from './xhr'
import qs from 'qs'

/**
 * 请求拦截器
 */
axios.interceptors.request.use((config) => {
    config.data = qs.stringify(config.data)

    return config
})

/**
 * 响应拦截器
 */
axios.interceptors.response.use((response) => {
    if (response.code !== 200) {
        alert('接口响应失败')
    }

    return response
})

/**
 * 接口请求方法
 */
const request = (method, option) => {
    return axios({
        method: method,
        url: 'https://study.noxussj.top' + option.url,
        data: option.data,
        headers: {
            'Content-Type': 'application/x-www-form-urlencoded'
        }
    })
}

export default {
    get: (option) => request('get', option),
    post: (option) => request('post', option),
    put: (option) => request('put', option)
}
import axios from './xhr'
import qs from 'qs'

/**
 * 请求拦截器
 */
axios.interceptors.request.use((config) => {
    config.data = qs.stringify(config.data)

    return config
})

/**
 * 响应拦截器
 */
axios.interceptors.response.use((response) => {
    if (response.code !== 200) {
        alert('接口响应失败')
    }

    return response
})

/**
 * 接口请求方法
 */
const request = (method, option) => {
    return axios({
        method: method,
        url: 'https://study.noxussj.top' + option.url,
        data: option.data,
        headers: {
            'Content-Type': 'application/x-www-form-urlencoded'
        }
    })
}

export default {
    get: (option) => request('get', option),
    post: (option) => request('post', option),
    put: (option) => request('put', option)
}

调用

javascript
import axios from './plugins/axios.js'

/**
 * 发起请求
 */
const p1 = axios.post({
    url: '/api/login',
    data: { account: 'test', password: '123456' }
})

p1.then((res) => {
    console.log(res.data)
})
import axios from './plugins/axios.js'

/**
 * 发起请求
 */
const p1 = axios.post({
    url: '/api/login',
    data: { account: 'test', password: '123456' }
})

p1.then((res) => {
    console.log(res.data)
})

修改后预览效果,依然是可以正常请求接口。