axios 的封装和 api 接口的统一管理

axios的封装和api接口的统一管理

1. 什么是 axios

Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中。

特性

  • 从浏览器中创建 XMLHttpRequests
  • 从 node.js 创建 http 请求
  • 支持 Promise API
  • 拦截请求和响应
  • 转换请求数据和响应数据
  • 取消请求
  • 自动转换 JSON 数据
  • 客户端支持防御 XSRF

2. 拦截器

axios 请求拦截器 (一般一个回调)

是什么:在真正发请求之前执行的一个回调函数。

作用: 对所有的请求做统一的处理,如追加请求头 、追加参数、界面loading提示等。

axios 响应拦截器

是什么:得到响应之后执行的一组回调函数

作用: 若请求成功,对成功的数据进行处理 ;若请求失败,对失败进行统一的操作。

注意:可以指定多个请求拦截器,先指定的先执行

// 添加请求拦截器
axios.interceptors.request.use(function (config) {
    // 在发送请求之前做些什么
    return config;
}, function (error) {
    // 对请求错误做些什么
    return Promise.reject(error);
});

// 添加响应拦截器
axios.interceptors.response.use(function (response) {
    // 对响应数据做点什么
    return response;
}, function (error) {
    // 对响应错误做点什么
    return Promise.reject(error);
});

3. 为什么要封装 axios

axios 本身就是封装好了的请求库,为什么我们要对其进行二次封装呢?这个原因很简单,和大多数的封装一样,目的是为了简化代码使用以及便于后期的更新与维护

axios的封装,主要是用来帮我们进行请求的拦截和响应的拦截。

在请求的拦截中我们可以携带userToken,post请求头、qs对post提交数据的序列化等。

在响应的拦截中,我们可以在接收到响应后先做一层操作,如根据状态码判断登录状态、授权,根据状态码来进行错误的统一处理等等。

axios接口的统一管理,是做项目时必须的流程。这样可以方便我们管理我们的接口,在接口更新时我们不必再返回到我们的业务代码中去修改接口。

4.axios 封装过程

4.1 安装axios
npm install axios
// or
yarn add axios
4.2 引入axios,进行二次封装
  1. 在项目的 src 文件夹下的 utils 文件夹下新建两个文件,分别为 request.js 文件和 manage.js 文件。其中 request.js 文件用来封装 axios,manage.js 文件用来封装 axios 常用的请求方式。

  2. 在 request.js 文件中引入 axios,对 axios 进行二次封装,代码如下。

    在 request.js 文件中主要对 axios 实例进行配置,包括请求地址、请求头、超时时间等,接着创建请求拦截器和响应拦截器。为保障服务器接口的安全性,会要求在进行 axios 封装时携带 token 调用每个接口,所以在请求拦截器中进行 token 配置,最后暴露 axios 实例。

    // request.js
    // 引入axios
    import axios from 'axios'
    import router from '../router'
    // ant design的全局提示插件
    import { message } from "ant-design-vue";
    
    /**
     * 【指定 axios的 baseURL】
     * 如果手工指定 baseURL: '/api'
     * 则映射后端域名,通过 vue.config.js
     * @type {*|string}
     */
    let apiBaseUrl = window._CONFIG['domianURL'] || "/api";
    // 根据不同环境设置不同的请求地址
    if (process.env.NODE_ENV === 'production') {
        // 生产模式
        apiBaseUrl = ''
    } else if (process.env.NODE_ENV === 'development') {
        // 开发模式
        apiBaseUrl = ''
    }
    console.log("apiBaseUrl= ", apiBaseUrl)
    
    // 创建 axios 实例
    const service = axios.create({
        // 请求地址
        baseURL: apiBaseUrl,
        // 设置默认get和post的请求头
        headers: {
            get: {
                'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8'
            },
            post: {
                'Content-Type': 'application/json;charset=utf-8'
            }
        },
        // 是否跨站点访问控制请求
        withCredentials: false,
        timeout: 600000, // 请求超时时间
        // 请求数据转换
        transformRequest: [(data) => {
            return JSON.stringify(data)
        }],
        // 响应数据转换
        transformResponse: [(data) => {
            if (typeof data === 'string' && data.startsWith('{')) {
                data = JSON.parse(data)
            }
            return data
        }]
    })
    
    // 添加请求拦截器
    service.interceptors.request.use(function (config) {
        // 发请求之前做些什么 根据业务场景 有的需要添加请求头 
        // console.log(config); //获取到了所有的请求配置项
        const token = localStorage.getItem("token")
        // 判断是否存在token,如果存在的话,则每个http header都加上token
        if (token) {
            // 将token设置到请求头中
            config.headers.Authorization = 'Bearer ' + token
        }
        return config;
    }, function (error) {    // 作用: 如果请求失败, 统一放在响应拦截器这里处理 
        error.data = {}
        error.data.msg = '服务器异常,请联系管理员!'
        return Promise.reject(error);
    })
    
    // 添加响应拦截器
    service.interceptors.response.use((response) => {
        return response.data
    }, error => {
        if (error.response) {
            console.log("------异常响应------", error.response)
            // let msg = showStatus(error.response.status)
            // alert(msg)
            switch (error.response.status) {
                case 400:
                    alert('请求错误(400)')
                    break
                case 401:
                    // alert('登录过期请重新登录!')
                    alert(error.response.data)
                    // 退出登录
                    localStorage.removeItem('token')
                    // 跳转到登录页面
                    router.push('/login')
                    break
                default:
                    alert('连接出错,请检查网络或联系管理员!')
            }
        }
        return Promise.reject(error);
    })
    
    const showStatus = (status) => {
        let message = ''
        switch (status) {
            case 400:
                message = '请求错误(400)'
                break
            case 401:
                message = '未授权,请重新登录(401)'
                // 退出登录
                localStorage.removeItem('token')
                // 跳转到登录页面
                router.push('/login')
                break
            case 403:
                message = '拒绝访问(403)'
                break
            case 404:
                message = '请求出错(404)'
                break
            case 408:
                message = '请求超时(408)'
                break
            case 500:
                message = '服务器错误(500)'
                break
            case 501:
                message = '服务未实现(501)'
                break
            case 502:
                message = '网络错误(502)'
                break
            case 503:
                message = '服务不可用(503)'
                break
            case 504:
                message = '网络超时(504)'
                break
            case 505:
                message = 'HTTP版本不受支持(505)'
                break
            default:
                message = `连接出错(${status})!`
        }
        return `${message},请检查网络或联系管理员!`
    }
    
    // 对外暴露
    export {
        service as axios
    }
    
4.3 封装 axios 请求方式
  1. 在项目的 src 文件夹下的 utils 文件夹下新建manage.js 文件,manage.js 文件用来封装 axios 常用的请求方式。

  2. 在 manage.js 文件中引入 request.js 文件,对 axios 常用的请求方式进行封装。代码如下:

// manage.js axios请求封装
import { axios } from '@/utils/request'

/** 
 * @param {String} url [请求的url地址]
 * @param {Object} params [请求时携带的参数]
 * */

// get
export function getAction(url, parameter) {
    return axios({
        url: url,
        method: 'get',
        params: parameter
    })
}

// post
export function postAction(url, parameter) {
    return axios({
        url: url,
        method: 'post',
        data: parameter
    })
}

// post
export function postFormAction(url, parameter) {
    return axios({
        url: url,
        method: 'post',
        params: parameter
    })
}

// post method= {post | put}
export function httpAction(url, parameter, method) {
    return axios({
        url: url,
        method: method,
        data: parameter
    })
}

// put
export function putAction(url, parameter) {
    return axios({
        url: url,
        method: 'put',
        data: parameter
    })
}

// deleteAction
export function deleteAction(url, parameter) {
    return axios({
        url: url,
        method: 'delete',
        params: parameter
    })
}

/**
 * 下载文件 用于excel导出
 * @param url
 * @param parameter
 * @returns {*}
 */
export function downFile(url, parameter, token) {
    return axios({
        url: url,
        params: parameter,
        method: 'get',
        responseType: 'blob',
        headers: {
            ['X-Access-Token']: token,
            'Access-Control-Allow-Origin': '*',
            'Access-Control-Allow-Methods': '*',
            'Access-Control-Allow-Headers': '*',
        }
    })
}
4.4 api 接口统一管理
  1. 在项目的 src 文件夹下新建一个 api 文件夹,里面有多个根据模块划分的接口 js 文件, 每个 js 文件都用来管理不同模块的接口。

  2. 例如,在 api 文件夹下新建一个有关登录功能的 login.js 文件,用来管理所有有关登录的接口。

    /**
     * 登录接口统一管理
     */
    
    // 导入 request 中创建的 axios 实例
    // import { axios } from '@/utils/request'
    // 导入 manage 中封装的请求方法
    import { postAction } from "@/utils/manage";
    
    const userApi = {
        login: '/api/login',
        logout: '/api/logout'
    }
    
    // 第一种方式
    export const login = data => postAction(userApi.login, data)   // 登录
    export const logout = () => postAction(userApi.logout, {})     // 退出登录
    
    // 第二种方式
    // export function login(parameter) {
    //     return axios({
    //         url: userApi.login,
    //         method: 'post',
    //         data: parameter
    //     })
    // }
    
    // export function logout(parameter) {
    //     return axios({
    //         url: userApi.logout,
    //         method: 'post',
    //         data: parameter
    //     })
    // }
    
4.5 在页面中的使用
  1. 可以按需导入使用

    // 在页面中的使用
    import { login, logout } from '@/api/login'
    
    // 登录
    login({ name: '小米', password: '123456' }).then(res => {
        console.log(res);
    })
    // 退出登录
    logout().then(res => {
        console.log(res);
    })
    
  2. 也可以挂载到 Vue.prototype 上,全局使用

    import Vue from 'vue'
    import App from './App.vue'
    // 导入路由文件
    import router from './router'
    // 导入 vuex 文件
    import store from './store/index'
    import { axios } from '@/utils/request'
    // 导入 manage 中封装的请求方法
    import { postAction } from "@/utils/manage"
    import { login, logout } from '@/api/login'
    
    // 将 axios 挂载到 Vue 的原型上
    Vue.prototype.$axios = axios
    Vue.prototype.$postAction = postAction
    Vue.prototype.$login = login
    
  3. 在组件中使用

    this.$postAction('/api/login', { name: '小米', password: '123456'}).then(res => {
        console.log(res)
    })
    
    this.$login({ name: '小米', password: '123456'}).then(res => {
        console.log(res)
    })
    
4.6 设置代理

什么是跨域:协议、域名、端口号不同请求,称之为跨域

http://localhost:8080/#/home ---- 前端项目本地服务器

http://39.98.123.211 ----后台服务器

解决可以使用:JSONP、CROS、代理。

proxy设置中间代理,可以帮我们向服务器发起请求。跨域问题是由浏览器的原因引起。

在 vue.config.js 文件里面进行设置

// vue.config.js

module.exports = {
    //  关闭eslint
    lintOnSave: false,
    // 代理跨域
    devServer: {
        //proxy:{'/api':{}},代理器中设置/api,项目中请求路径为/api的替换为target
        proxy: {
            '/api': {
                // http://192.168.0.19:8082/api
                target: 'http://192.168.0.19:8082/api',//代理地址,这里设置的地址会代替axios中设置的baseURL
                changeOrigin: true,// 如果接口跨域,需要进行这个参数配置
                //ws: true, // proxy websockets
                //pathRewrite方法重写url
                pathRewrite: {
                    '^/api': '/'
                    //pathRewrite: {'^/api': '/'} 重写之后url为 http://192.168.1.16:8085/xxxx
                    //pathRewrite: {'^/api': '/api'} 重写之后url为 http://192.168.1.16:8085/api/xxxx
                }
            }
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Axios是一个基于Promise的HTTP客户端工具,用于发送异步请求到服务器并处理响应数据。针对不同的接口,我们通常需要编写不同的请求代码,这样会造成代码的冗余、可维护性变差等问题。因此,将Axios进行封装,实现统一处理接口是十分必要的。 首先,我们需要定义一个统一处理接口工具类,该类包含了请求的各个参数,如headers、params、data、url等,同时还需要定义一些公共操作,比如设置请求头、设置响应数据格式、设置过期时间等。 然后,我们可以根据实际需求,提供一个简单易用的API接口,以供使用。在使用API接口时,只需要传入参数并调用即可,封装的工具类会将参数整合后发出请求,并对响应数据进行处理,返回符合要求的数据。 另外,在封装过程中,我们还需要考虑一些异常情况的处理,比如请求超时、网络出错、服务器异常等,这些异常情况都需要有相应的处理方式,例如重试、报警、记录日志等。 通过以上的封装,我们可以使得接口的调用变得更加简单、规范,同时还可以大幅提高代码的复用性、可维护性和可扩展性。 ### 回答2: 随着前端技术的不断发展,前后端分离的开发模式已经成为了越来越多的企业和开发者的选择。在这种模式下,前端需要向后端请求数据,完成页面渲染和交互操作。而axios作为一款广泛应用的http请求工具,在前端开发中也有着重要的地位。 在实际开发中,通常需要对axios进行封装,以便于统一处理接口,提高代码复用性和维护性。而在封装过程中,主要需要考虑以下几个方面: 1. 统一接口格式以便于处理 不同的后端接口可能有着不同的返回格式,为了方便处理数据,需要将不同接口的返回格式进行统一。通常可以定义一个统一的数据格式,如 { code: 200, message: 'success', data: {}, } 以此来包裹不同接口的数据返回。 2. 处理请求和响应拦截 在封装过程中,需要对请求和响应进行拦截,以便于处理请求头、请求参数、响应状态码等信息。请求拦截可以用于设置全局请求头、请求参数,响应拦截可以用于处理错误信息、统一处理响应数据等操作。 3. 统一处理错误信息 当后端返回错误信息时,需要对错误信息进行统一处理,如提示用户、记录日志等操作。因此,需要在封装过程中考虑到错误处理的逻辑,以便于在出现错误时进行统一处理。 4. 优化请求性能 在实际开发中,为了保证应用的性能和用户体验,需要优化http请求,如缓存、懒加载等操作。 以上就是对axios封装统一处理接口的一些思考和总结。通过封装,可以提高代码的复用性和维护性,优化开发效率和用户体验,是一项非常重要的前端开发技能。 ### 回答3: 随着前端技术的不断发展,前端页面需求也越来越复杂,前后端分离的思想被广泛应用,而axios作为一款常用的HTTP客户端库,成为了前端开发中不可或缺的工具之一。在日常开发中,针对不同的接口请求,我们需要编写很多的axios请求代码,这样会造成代码量较大、维护困难等问题。因此,开发者一般会采用一定的封装方法,如axios封装统一处理接口,来解决这样的问题。 axios封装统一处理接口的具体实现方法是,将axios中的请求、响应拦截器进行封装处理,实现请求前的处理、响应后的处理以及异常处理等功能。我们可以将某些相同的参数如headers、timeout或baseURL等配置在一个统一的配置文件中,以提高代码的可复用性和可维护性。我们也可以自定义方法如get、post和put等,根据业务需求来定义统一处理接口。 使用axios封装统一处理接口的好处有很多。首先,可以将所有的请求和响应进行统一处理,这样可以减少重复代码,提高代码的可读性和复用性。同时,可以在拦截器中统一处理错误信息,实现异常处理,提高代码的容错性和健壮性。其次,可以更好的管理接口的访问权限和处理方式,保证代码的安全性和稳定性。最后,可以更方便地进行接口管理和调用,提高了开发效率和团队协作的效果。 总之,使用axios封装统一处理接口,可以提高代码的可维护性、重用性和健壮性,同时也方便了接口管理和调用,为项目开发提供了更好的支持。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值