zoukankan      html  css  js  c++  java
  • Axios 网络请求组件封装 (鉴权、刷新、拦截)

    一、前言

    注意:本教程需要你对axios有一定的了解,不适用于小白(只能借鉴,希望你能自己动手),注释都写的很清楚。此封装并非完整版,已进行部分删减修改操作,但仍然适用于大部分业务场景,如果不适用于你项目的特定业务场景,请自行修改。


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

    Axios的特性如下:

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

    二、安装及其使用

    安装

    使用 npm:

    $ npm install axios
    

    使用 bower:

    $ bower install axios
    

    使用 cdn:

    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
    

    三、开始封装

    axios封装 (api.js)

    import axios from 'axios'                       //网络请求组件
    import Qs from 'qs'                             //数据解析库(使用JSON亦可,本文未使用QS,如需要,可替换JSON为QS)
    import { Message } from 'element-ui'            //element组件,本文使用message消息提示(可根据自行需要进行替换其他TOAST)
    import router from '../router'                  //路由引入,拦截访问,进行路由跳转
    import * as api from '../api/commonApi'               //封装axios请求组件,在特定业务场景使用里面的请求
    import store from '../store/index'
    
    //axios网络封装请求开始
    
    
    var service = axios.create({
        // process.env.NODE_ENV获取当前业务场景的环境,以使用不同的api地址。API_ROOT为自定义api请求地址(请自行替换)
        baseURL: process.env.NODE_ENV === 'production' ? process.env.API_ROOT : process.env.NODE_ENV === 'presentation' ? process.env.API_ROOT : process.env.API_ROOT,
        timeout: 100000,
    })
    //获取登录时存储的sessionStorage
    let getToken = window.sessionStorage.getItem('token');
    //进行数据格式的转换
    let parseToken = JSON.parse(getToken);
    //拦截网络请求开始
    service.interceptors.request.use(config => {
        // 判断token是否存在,如果存在,就给请求头加上token
        if (sessionStorage.getItem('token')) {
            config.headers.Authorization = parseToken.token_type +" "+ parseToken.access_token;
        }
        // 检测如果请求为post,进行转换为JSON字符串(一般情况下不需要)
        if (config.method === 'post') {
            config.data = JSON.stringify(config.data)
        }
        // 设置请求头
        // 请求头常见的有以下几种方式,可根据需要自行修改
        // ’application/json’,’application/x-www-form-urlencoded’,’multipart/form-data’
        // config.headers = {
        //    'Content-Type':'application/x-www-form-urlencoded'
        // }
        return config;
    },error => {
        // 请求错误消息提示
        Message({
            message: error.message,
            type: "error"
        });
        return Promise.reject(error.data.error.message);
     });
    
    
    //返回状态判断(添加响应拦截器)
    service.interceptors.response.use(response => {
    
        return response
        // 返回数据进行消息提示
        if(!response.data){
            Message({
                message: "数据响应失败",
                type: "warning"
            });
        }
    },error => {
            //获取错误信息
            const config = error.config
            //判断错误信息的url是否为刷新接口的url,process.env.API_ROOT请自行替换为请求地址,如:192.168.1.1
            if(config.url === process.env.API_ROOT +"/refreshToken"){
                Message({
                    message: '数据刷新失败,请重新登录再进行操作。',
                    type: 'error',
                    duration: 1.5 * 1000
                })
                //清除vuex及其sessionStorage等信息
                store.commit('remove_login_info')
                //进行路由跳转
                router.push('/login')
                return
            }
            //拦截response 返回状态码,如果为401需要重新进行token刷新,调用请求并传入参数
            if (error.response.status === 401) {
                const refresh = new Promise((resolve, reject) => {
                    api.refreshToken(store.state.usertonken.refresh_token).then((resp) => {
                        if(resp.data.code === 2000000){
                            this.loginloading = true;
                            //重新添加token到sessionStorage
                            window.sessionStorage.setItem('token',JSON.stringify(resp.data.data))
                            //用vuex重新设置基本信息
                            store.commit('add_login_info',resp.data.data)
                            this.loginloading = false;
                            //修改_retry
                            config._retry = true;
                            let getToken = window.sessionStorage.getItem('token');
                            //进行数据格式的转换
                            let parseToken = JSON.parse(getToken);             
                            //修改原请求的token
                            config.headers.Authorization = parseToken.token_type + " " +parseToken.access_token;
                            config.baseURL = '';
                            resolve(axios(config));
                        }
                    }).catch(function (error) {
                        return Promise.reject(error);
                    });
                });
                return refresh;
            }
    
            //拦截response 返回状态码,如果为400进行错误消息提示
            if (error.response.status === 400) {
                Message({
                    // message:error.response.data.err_msg,
                    message:'操作失败',
                    type: "warning",
                    duration: 1.5 * 1000
                });
            }
            //拦截response 返回状态码,如果为403进行错误消息提示
            if (error.response.status === 403) {
                Message({
                    message: '暂无权限,请重新登录再进行操作。',
                    type: 'error',
                    duration: 1.5 * 1000
                })
                //清除vuex及其sessionStorage等信息
                store.commit('remove_login_info')
                //进行路由跳转
                this.$router.push({path:'/login'})
            }
            return Promise.reject(error);
        }
    
    );
    service.install = (Vue) => {
        Vue.prototype.$http = axios
    }
    
    export default service
    
    
    

    刷新token的方法

    
    import api from './api'   //引入axios网络请求封装组件
    
    
    //进行请求方法的封装,并传入请求参数(非必需)
    //token刷新方法
    export function refreshToken(refresh_token){
        let data = { refresh_token}
        return fetch({
            url:'refreshToken',
            method: 'post',
            data,
        })
    }
    
    
    

    调用方式

    import api from './api'
    
    api({
        url: '请求地址',
        method: 'post',
        data: 请求参数
    }).then((resp) => {
       console.log(resp.data)
    })
    

    后记

    此封装纯属个人自用,为了方便大家使用,已进行部分修改和整理。如果你有任何疑问或者建议,欢迎留言进行评论。如果你觉得帮助到了你,请分享给更多的人。感谢你的支持!!!

  • 相关阅读:
    MySQL5.7修改字符集
    MySQL-day1数据库的安装与介绍
    简述Python中的break和continue的区别
    Python实现用户交互,显示省市县三级联动的选择
    Mac升级Node.js和npm到最新版本指令
    vue+Typescript初级入门
    js-md5加密
    create-react-app 工程,如何修改react端口号?
    chrome安装react-devtools开发工具插件
    mac下更新node版本
  • 原文地址:https://www.cnblogs.com/ceet/p/10020216.html
Copyright © 2011-2022 走看看