axios二次封装

453 阅读6分钟

封装好的简洁版

/*
ajax请求函数模块
返回值: promise对象(异步返回的数据是: response.data)
 */
import iView from 'iview'
import axios from 'axios'

// 默认配置
axios.defaults.baseURL = 'http://localhost:8081/这是优先级最低的url' // 优先级比axios实例要低
axios.defaults.headers.post['Content-Type'] = 'application/json;charset=utf-8'

// 创建一个axios实例 ==> instanceOne
const instanceOne = axios.create()
instanceOne.defaults.baseURL = 'http://localhost:8081/soft' // 实例的baseurl

let cancel

function ajax ({
                   sourceAxios = axios, // 配置多源默认接口,可传axios的实例instanceOne,或者直接传axios
                   url,
                   params = {}, // Get请求传的参数
                   data = {}, // Post请求传的参数
                   method = 'GET',
                   cancelBefore = false, // 是否强制取消上一个没完成的请求
                   errHandle = false, // 单独提示错误信息设置,为true全局提示无效
                   contentType = 'application/json;charset=utf-8', // post请求默认请求头
               }) {
    return new Promise((resolve, reject) => {

        // 处理method(转大写) 防止请求类型写成小写形式
        method = method.toUpperCase()

        // loading全局设置,在拦截器中使用,可注释
        iView.LoadingBar.config({
            color: '#33a3dc',
            failedColor: '#f0ad4e',
            height: 3
        })

        // 请求拦截器1 设置loading效果与是否之前取消未完成的请求
        sourceAxios.interceptors.request.use(
            config => {
                if (cancelBefore) { // 在准备发请求前, 取消未完成的请求
                    if (typeof cancel === 'function') { // 当cancel是函数时表示上个请求未完成
                        iView.LoadingBar.finish()
                        cancel('取消上一个未完成的请求')
                    }
                    // 添加一个cancelToken的配置
                    config.cancelToken = new axios.CancelToken((c) => { // c是用于取消当前请求的函数
                        // 保存取消函数, 用于之后可能需要取消当前请求
                        cancel = c // 把函数c赋给cancel
                    })
                }
                iView.LoadingBar.start() // 加载iview的Loading效果
                
                return config
            }, error => {
                return Promise.reject(error)
            }
        )

        // 响应拦截器
        sourceAxios.interceptors.response.use(
            response => {
                iView.LoadingBar.finish()
                cancel = null // 响应成功把cancel置为null

                return response
            }, (error) => {
                iView.LoadingBar.finish()

                console.log('第一个响应拦截器执行fail')
                console.log(error)

                if (axios.isCancel(error)) { // 取消请求的错误
                    cancel = null
                    console.log('请求取消的错误', error.message) // 做相应处理
                    return new Promise(() => {  // 中断promise链接
                    })
                } else { // 请求出错了
                    cancel = null
                    return Promise.reject(error) // 将错误向下传递 throw error
                }
            }
        )
        
        // 执行异步ajax请求
        let promise
        if (method === 'GET') {
            // 发送get请求
            promise = sourceAxios({url, params})
        } else {
            // 发送post请求
            promise = sourceAxios({
                method: 'POST',
                url,
                data,
                headers: {'Content-Type': contentType}
            })
        }

        promise.then(response => {
            const resMess = { // 封装返回成功的数据信息
                data: response.data,
                status: response.status,
                statusText: response.statusText
            }
            resolve(resMess)

        }).catch(err => { // 失败了调用reject()
            if (!errHandle) { // 全局错误的提示
                iView.Message.error('网络错误:' + err) // 若调用接口失败返回信息
            }
            reject(err)
        })
    })
}

export default ajax

各类杂项以及测试代码

/*
ajax请求函数模块
返回值: promise对象(异步返回的数据是: response.data)
 */
import iView from 'iview'
import axios from 'axios'

// 默认配置
axios.defaults.baseURL = 'http://localhost:8081/这是优先级最低的url' // 优先级比axios实例要低
// axios.defaults.timeout = 10000 // 优先级比axios创建的实例要低
// axios.defaults.headers.post['Content-Type'] = 'application/json;charset=utf-8'
// axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded'

// 创建一个axios实例 ==> instanceOne
const instanceOne = axios.create()
instanceOne.defaults.baseURL = 'http://localhost:8081/soft' // 实例的instanceOne baseurl

// 创建另一个axios实例 ==> instanceTwo
const instanceTwo = axios.create({ // instanceTwo实例的默认配置项
    baseURL: 'http://localhost:8328/soft', //baseURL会放到url前面
    timeout: 10000, // 指定请求超时的毫秒数(0 表示无超时时间),超过 timeout 的时间,请求将被中断
    withCredentials: true, // 设置cross跨域 并设置访问权限 允许跨域携带cookie信息,跨域请求时是否需要使用凭证
    headers: {}, // 请求头
    transformRequest: [function (data) {
        // 这里可以在发送请求之前对请求数据做处理,比如form-data格式化等,这里可以使用开头引入的Qs(这个模块在安装axios的时候就已经安装了,不需要另外安装)
        data = Qs.stringify({});
        return data;
    }],

    transformResponse: [function (data) {
        // 这里提前处理返回的数据

        return data;
    }],
    responseType: 'json', // 表示服务器响应的数据类型,可以是 'json'(默认), 'arraybuffer', 'blob', 'document', 'text', 'stream'
    validateStatus: function (status) {
        // validateStatus 定义对于给定的HTTP 响应状态码是 resolve 或 reject promise 。
        // 如果 validateStatus 返回 true (或者设置为 null 或 undefined),promise 将被 resolve;
        // 否则,promise 将被 rejecte
        return status >= 200 && status < 300 // 默认的
    },
    // `cancelToken` 指定一个取消令牌,可以用来取消请求
    // (详情见Cancellation 部分)
    // cancelToken: new CancelToken(function (cancel) {
    // })
})

let cancel

function ajax ({
                   sourceAxios = instanceOne, // 配置多源默认接口
                   url,
                   params = {},
                   data = {},
                   method = 'GET',
                   cancelBefore = false, // 是否强制取消上一个没完成的请求
                   errHandle = false, // 单独提示错误信息设置,为true全局提示无效
                   contentType = 'application/json;charset=utf-8', // post请求默认请求头
               }) {
    return new Promise((resolve, reject) => {

        // 处理method(转大写) 防止请求类型写成小写形式
        method = method.toUpperCase()

        // loading全局设置
        iView.LoadingBar.config({
            color: '#33a3dc',
            failedColor: '#f0ad4e',
            height: 3
        })

        // 请求拦截器1 设置loading效果与是否之前取消未完成的请求
        sourceAxios.interceptors.request.use(
            config => {

                if (cancelBefore) { // 在准备发请求前, 取消未完成的请求
                    if (typeof cancel === 'function') { // 当cancel是函数时表示上个请求未完成
                        iView.LoadingBar.finish()
                        cancel('取消上一个未完成的请求')
                    }
                    // 添加一个cancelToken的配置
                    config.cancelToken = new axios.CancelToken((c) => { // c是用于取消当前请求的函数
                        // 保存取消函数, 用于之后可能需要取消当前请求
                        cancel = c // 把函数c赋给cancel
                    })
                }
                iView.LoadingBar.start() // 加载iview的Loading效果
                // iView.Spin.show()
                // 自定义 loading
                /* iView.Spin.show({
                    render: (h) => {
                        return h('div', [
                            h('Icon', {
                                'style': 'animation: ani-demo-spin 1s linear infinite;', // 动画效果
                                props: { // 图标样式设置
                                    type: 'ios-loading',
                                    size: 30,
                                    color: 'blue',
                                }
                            }),
                            h('div', { // 显示字体样式设置
                                'style': 'color: blue;font-size:20px'
                            }, 'Loading') // 文字
                        ])
                    }
                }) */
                console.log('第一个请求拦截器执行')

                return config
            }, error => {
                return Promise.reject(error)
            }
        )

        // 请求拦截器2
        // sourceAxios.interceptors.request.use(
        //     config => {
        //         console.log('第二个请求拦截器执行')
        //         return config
        //     }, err => {
        //         return Promise.reject(err)
        //     }
        // )

        // 响应拦截器
        sourceAxios.interceptors.response.use(
            response => {
                iView.LoadingBar.finish()
                // iView.Spin.hide()
                cancel = null // 响应成功把cancel置为null
                console.log('第一个响应拦截器执行')

                return response
            }, (error) => {
                iView.LoadingBar.finish()

                console.log('第一个响应拦截器执行fail')
                console.log(error)

                if (axios.isCancel(error)) { // 取消请求的错误
                    cancel = null
                    console.log('请求取消的错误', error.message) // 做相应处理
                    return new Promise(() => {  // 中断promise链接
                    })
                } else { // 请求出错了
                    cancel = null
                    return Promise.reject(error) // 将错误向下传递 throw error
                }
            }
        )
        // 响应拦截器
        // sourceAxios.interceptors.response.use(
        //     response => {
        //         console.log('第二个响应拦截器执行')
        //         return response
        //     }, (err) => {
        //         console.log('第二个响应拦截器执行fail')
        //
        //         iView.LoadingBar.finish()
        //         return Promise.reject(err)
        //     }
        // )

        // 当设置两个请求拦截器和两个响应拦截器 执行的打印输出顺序
        // 第二个请求拦截器执行 => 第一个请求拦截器执行 => 第一个响应拦截器执行 => 第二个响应拦截器执行

        // 执行异步ajax请求
        let promise
        if (method === 'GET') {
            // 发送get请求
            promise = sourceAxios({url, params}) // 或 promise = sourceAxios.get(url, {params})
        } else {
            // 发送post请求
            promise = sourceAxios({
                method: 'POST',
                url,
                data,
                headers: {'Content-Type': contentType} // 告诉服务器请求体的格式是json
            })

            /*promise = sourceAxios.post(
                url,
                data,
                {
                    headers: {'Content-Type': 'application/json;charset=utf-8'}  // 告诉服务器请求体的格式是json
                })*/
        }

        promise.then(response => {
            const resMess = { // 返回成功的数据信息
                data: response.data,
                status: response.status,
                statusText: response.statusText
            }
            resolve(resMess)

        }).catch(err => {
            // 失败了调用reject()
            if (!errHandle) { // 全局错误的提示
                iView.Message.error('网络错误:' + err) // 若调用接口失败返回信息
            }
            reject(err)
        })
    })
}

export default ajax