axios及二次配置

864 阅读3分钟

一、axios概念

axios:基于Promise封装的ajax库(核心还是ajax的四步操作)

  • ajax请求一般采用异步
    • ajax的串行:第一个接口请求成功,才能继续请求第二个...
    • ajax的并行:同时发送多个接口请求,当所有接口都请求成功,再去执行某些事情 => Promise.all
  • 基于Promise管理ajax的异步操作 Fetch:浏览器新增的API,默认就是基于Promise管理的(核心不是XMLHttpRequest)
//传统方案会引发回调地狱
$.ajax({
    url: 'http://127.0.0.1/api1',
    success: result => {
        $.ajax({
            url: 'http://127.0.0.1/api2',
            success: result => {
                ...
            }
        })
    }
})
//返回的是promise实例
axios.get('http://127.0.0.1/api1').then(response => {
    return axios.get('http://127.0.0.1/api2');
}).then(response => {
    ...
})

二、axios学习目录

  • axios的的基础使用

  • axios的二次封装

    • 拦截器
    • 一些常规配置

    1、axios的基础使用

//返回的都是Promise实例
axios([config])
axios([url], [config])
axios.get/head/delete/options([url], [config])
axios.post/put([url], [data], [config])
//axios.get使用
let baseUrl = 'http://127.0.0.1';
axios.get('/api1', {
    baseUrl,  //请求地址的公共部分:最后请求的地址 baseUrl + url
    headers: {
        'Content-Type': 'application-www-form-urlencoded'
    }, //自定义请求头信息
    timeout: 0, //在CORS跨域请求中,是否允许携带资源凭证
    responseType: 'json', //预设服务器返回的数据内容:服务器该返回啥还是啥(后台决定返回格式),
    //而预设的意思是:把服务器返回的结果,处理成想要的数据格式,支持设定的格式有:'arraybuffer', 'blob','document','json','text','stream')
    validateStatus: function(status){
        return status >= 200  && status <= 300;
    }, //它规定了请求结果中,哪些状态码代表请求成功,哪些代表失败,从而决定执行then还是catch
    params: {
        name: 'luban',
        age: 4
    }//get请求传递参数,最后都会拼接到url的末尾(必须是一个无格式对象或URLSearchParams对象)
}).then(response => {
    //从服务器成功获取对象
    //status / statusText:状态码的描述
    //request:原生的xhr对象
    //headers:存储部分响应头信息
    //config:我们发送请求的配置项
    //data:服务器响应主体的信息(我们获取的数据)
    return response.data;
}).catch(reason => {
    //从服务器获取失败数据
    //返回的是ERROR类的实例
    //message:错误的信息
    //request:原生的xhr对象
    //config:我们发送请求的配置项
    //response:等同于成功的response,但是可能没有,如果向服务器发请求,服务器接收 ,但是返回非2开头的状态码(虽然失败,但是最起码告诉我们具体的结果了),这种是有response。如果请求没有到达服务器(如断网了),则没有response
    console.log('失败');
    return Promise.reject(reason.message);
}).then(result => {
    //result = response.data
    console.log('响应主体信息', result);
})
axios.post('/user/update', {
    userId: 1,
    desc: '鲁班真可爱'
}, {
    baseUrl,
    //post是基于请求主体传递给服务器信息
    /*
    传递的数据格式:form-data / x-www-from-urlencoded / raw / binary / GraphQL
    form-data:一般用于表单提交或者文件流(文件上传)Content-type: multipart/form-data
    x-www-from-urlencoded: xxx=xxx&xxx=xxx application/x-www-from-urlencoded
    raw: 文本格式 "普通文本 text/plain"  "json字符串 application/json"
    binary: 进制编码格式 application/octet-stream
    */
    
    headers: {
        "Content-type": "application/x-www-from-urlencoded"
    },
    //transformRequest:把请求主体传递的信息 在发送给服务器之前,变成我们想要的格式
    transformRequest: data => {
        //data就是我们配置的对象
        return Qs.stringify(data);
    }
})

2、axios的二次封装

/*
- axios库中的默认配置
- 提取的公共参数配置  axios.defaults
- 发送请求时单独写的配置,axios.get([url], [config])
优先级自下而上
*/

//需求1:真实项目中,我们可能基于环境变量(开始/测试/生产)控制地址前缀不一样
let env = process.env.NODE_ENV; //获取webpack/package.json中配置的环境变量
switch(env) {
    case "production": 
        axios.defaults.baseURL = "http://xxx.x.x.x/xxxx";
        break;
    case "test": 
        axios.defaults.baseURL = "http://xxx.x.x.x/xxxx";
        break;
    default:
        axios.defaults.baseURL = "http://xxx.x.x.x/xxxx";
}

axios.defaults.baseURL = "http://127.0.0.1/8080";
axios.defaults.timeout = 10000;
axios.defaults.withCredentials = true;
axios.defaults.headers = {
    "Content-type": "application/x-www-from-urlencoded"
}
axios.defaults.transformRequest = data => Qs.stringify(data);
axios.defaults.validateStatus = status => (status >= 200  && status <= 300);
//请求拦截器:在我们把数据发送给服务器之前,拦截到我们设置的config,然后二次配置
axios.interceptors.request.use(config => {
    //config: 存储现有配置项
    
    //携带token
    let token = localStorage.getItem('token');
    token && (config.headers.Authorization = token);
    return config;
});
//响应拦截器
axios.interceptors.response.use(response => {
    //response: 成功返回的结果
    return response.data;
}, reason => {
    //失败返回的信息
    //统一在这里针对失败的结果做不同的提示后者处理
    if (reason.response) {
        //服务器返回信息,只是状态码不是2开始的:根据不同状态码做提示
        switch(reason.response.status) {
            case 401:
                //权限问题
                break;
            case 403:
                //Token过期
                break;
            case 404:
                //地址错误
                break;
        }
    } else {
        //需要检验是否断网
        if(!navigator.onLine) {
            
        }
    }
    return Promise.reject(reason.message);
});