zoukankan      html  css  js  c++  java
  • axios的二次封装和api接口规范

    fetch是浏览器内置的类,进行数据请求,天生就是基于promise进行管理的

    axios是基于ajax和promise进行封装的库

    下面是axios封装基本需求

    // 二次封装axios
    import axios from 'axios';
    import { config } from 'process';
    import qs from qs;
    // 根据环境变量区分接口的默认地址
    switch(process.env.NODE_ENV){
        case "production": //生产环境
            axios.defaults.baseURL = "http://api.yanggengzhen.com";
        break;
        case "test": //测试环境
            axios.defaults.baseURL = "http://192.168.20.12:8080";
        break;
        default:
            axios.defaults.baseURL = "http://127.0.0.1:3000"
    }
    // 设置超时时间和跨域是否允许携带凭证
    axios.defaults.timeout = 10000;
    axios.defaults.withCredentials = true;
    
    // 设置POST请求头,告知服务器请求主体的数据格式(看服务器要求什么格式)
    // 就算是post请求有些人会要求以xxx=xxx&xxx=xxx的形式传参,这就是x-www-form-urlencoded格式
    axios.defaults.headers['Content-Type'] = 'application/x-www-form-urlencoded';
    // 将传参的json格式的data转化为xxx=xxx&xxx=xxx
    axios.defaults.transformRequest = data => { qs.stringify(data)} 
    
    //设置请求拦截器
    // 客户端发送请求 ->[请求拦截器] -> 服务器
    // TOKEN校验(JWT):接收服务器返回的token,存储到vuex/本地存储中,每一次向服务器发请求,我们应该把token带上
    axios.interceptors.request.use( config =>{ // config表示请求头的配置项
        // 携带上token
        let token = localStorage.getItem('token');
        token && (config.headers.Authorization = token);
        return config; //不返回config的话后端接收一片空白
    },error=>{
        return Promise.reject(error);
    })
    // 自己设置哪些状态码表示成功,哪些表示失败(只要是返回2xx或者3xx都算请求成功,响应拦截器就会走第一个,否则走error)
    axios.default.validateStatus = function (status){ //状态码
        return /^(2|3)d{2}$/.test(status);
    }
    // 响应拦截器
    // 服务器返回信息 -> [拦截的统一请求] ->客户端js获取到信息
    axios.interceptors.response.use(response=>{
        return response.data; //只拿响应主题内容
    },error=>{
        let { response } = error;
        if(response){
            // 服务器有返回结果(常用的错误状态码)
            switch (response.status){
                case 401: //当前请求需要用户验证(一般是未登录)(权限)
                    break;
                    // 一般操作是跳转路由或者弹出蒙层
                case 403: //服务器已经理解请求,但是拒绝执行它(一般是token过期)
                localStorage.removeItem('token')
                // 跳转到登陆页
                    break;
                case 404: //找不到页面或者请求失败,请求所希望得到的资源未被放在服务器上发现
                    break;
            }
            return Promise.reject(response)
        }else{
            // 服务器连结果都没有返回
            if(!window.navigator.onLine){
                // 断网处理:可以跳转到断网页面(把路由导进来,重新连接的时候可以go(-1),路由跳转,路由信息保存)
                return
            }
            return Promise.reject(error) //服务器返回结果都没有,并且也没有断网,此时应该是服务端的问题
        }
    })
    export default axios;

    fetch封装库基本需求

    // fetch
    import qs from 'qs'
    // 根据环境变量进行接口区分
    let baseUrl = '';
    let baseURLArr = [
        {
            type:'development',
            url:'http://127.0.0.1:9000'
        },
        {
            type:'test',
            url:'http://192.168.20.15:9000'
        },
        {
            type:'production',
            url:'http://api.yanggengzhen.com'
        }
    ]
    baseURLArr.forEach(item=>{
        if(process.env.NODE_ENV === item.type){
            baseUrl = item.url
        }
    })
    // 前端请求的时候,传参的时候转变为url+? query
    // request(url,{
    //     params:{
    
    //     }
    // })
    export default function request(url,options={}){
        url = baseUrl + url; //请求的url ,配置项,如果不传,默认为空对象
        // get系列请求的处理
        !options.methods?options.methods = 'GET':null;
        if(options.hasOwnProperty('params')){
            if(/^(GET|DELETE|HEAD|OPTIONS)$/i.test(options.methods)){ //判断是否是get请求
                const ask = url.includes('?')?'&':'?';
                url += `${ask}${qs.stringify(params)}`
            }
            delete options.params;
        }
        // 合并配置项
        options = Object.assign({
            //允许跨域携带资源凭证same-origin同源可以 omit都拒绝
            credentials:'include',
            // 设置请求头
            header:{}
        },options);
        options.headers.Accept = 'application/json';
        // token的校验
        const token = localStorage.getItem('token');
        token && (options.header.Authorization = token);
    
        // post请求的处理
        if(/^(POST|PUT)$/i.test(options.methods)){
            !options.type ? options.type = 'urlencoded' :null;
            if(options.type === 'urlencoded'){
                options.headers['Content-Type'] = 'application/x-www-form-urlencoded';
                options.body = qs.stringify(options.body);
            }
            if(options.type === 'json'){
                options.headers['Content-Type'] = 'application/json';
                options.body = JSON.stringify(options.body);
            }
        }
        return fecth(url,options).then(response =>{
            // fecth和axios ajax的区别:不论服务器返回什么,都会成功触发.then
            //返回的结果可能是非200状态码
            if(!/^(2|3)d{2}$/.test(response.status)){
                switch (response.status) {
                    case 401: // 当前请求需要用户验证(一般是未登录)
                        break;
                    case 403: //服务器已经理解请求,但是拒绝执行它(一般是token过期)
                        break;
                    case 404: //请求失败,请求所希望得到的资源未被再服务器上发现
                        break;
                }
                return Promise.reject(response)
            }
        }).catch(error => {
            //断网处理
            if(!window.navigator.onLine){
                 //断开网络了。可以让其跳转到断网页面
                return;
            }
            return Promise.reject(error)
        })
    }

    最后制作成统一接口export出去,再到vue原型链上挂载属性,调用即可

     

     

     

  • 相关阅读:
    vue+element目录树默认展开和选中
    vue+element目录树初始化和销毁
    vue父组件通过ref获取子组件的值
    [moka同学笔记转载]Yii2使用$this->context获取当前的Module、Controller(控制器)、Action等
    [moka同学笔记]JS学习 鼠标事件
    [moka同学笔记]phpStudy for Linux (lnmp+lamp一键安装包)
    [转载]php中序列化与反序列化
    [Node.js学习]初之体验
    [moka同学笔记转载]Yii 设置 flash消息 创建一个渐隐形式的消息框
    [moka同学笔记转载]yii2.0 rbac权限学习笔记
  • 原文地址:https://www.cnblogs.com/gengzhen/p/14054490.html
Copyright © 2011-2022 走看看