你还不会axios?

1,370 阅读6分钟

什么是axios

axios是一个基于promise封装的ajax网络请求库,通过promise来进行管控,可以有效的解决ajax回调地狱的问题。

axios基础语法

axios的属性和方法:

  1. Axios: 实现promise管控ajax请求的一个类方法,axios执行的时候返回的其实就是一个Axios的实例
  2. CancelCancelToken: 在发送请求的工程中控制中断请求
  3. all: 通过promise.all来进行控制的,当所有的请求成功返回的实例才是成功态
  4. spread: 结合all获取请求数组中的promise实例,解析all的结果
  5. create: 创建axios的实例,多用于项目中有多个服务器共同工作时,请求不同服务器通过不同的实例对象,并且添加不同的默认配置
  6. default: 指向axios函数自己
  7. defaults: 给请求添加的默认配置项
    • adapter: 自定义处理请求,一般不用
    • headers: 请求头信息
      • 自定义请求头
      • common: 默认的请求头信息,默认->{Accept: "application/json, text/plain, */*"},发送时自动拼接到headers
      • get/delete/head: GET类请求的请求头信息,无默认,发送时自动拼接到headers上
      • post/put/patch: POST类请求的请求头信息,默认->{"ConTent-Type":"application/x-www-form-urlencoded"},发送时自动拼接到headers
    • maxBodyLength: -1 定义允许的请求内容的最大尺寸
    • maxContentLength: -1 定义允许的响应内容的最大尺寸
    • timeout: 0 设置超时时间
    • transformRequest(): 在发送请求前进行一些配置处理,一般做主体信息转换
    • transformResponse(): 转换响应主体response的内容,一般不用
    • validateStatus(): 设置状态码校验规则,不符合规则就代表失败
    • xsrfCookieName: "XSRF-TOKEN" 防止XSRF攻击
    • xsrfHeaderName: "X-XSRF-TOKEN" 防止XSRF攻击
  8. request: 发送请求
  9. isCancel(): 判断请求是否是中断的(断网或者自己调用Cancel中断)
  10. isAxiosError(): 判断是否时axios层面的错误
  11. iterceptors: 拦截器
    • resquest: 请求拦截器,一般做携带token标识
    • response: 响应拦截器,对响应做统一处理
  12. get/delete/head/options: GET类请求快捷方式
  13. post/put/patch: POST类请求快捷方式

axios配置项 axios(options) -> options:

  1. baseURl: 默认地址
  2. url: 加上baseURL形成完整的地址
  3. method: 请求方式
  4. transformRequest: 同上
  5. transformResponse: 同上
  6. headers: 同上
  7. params: get请求时的参数,POST请求下不起作用
  8. paramsSerializer(): 将get的参数序列化
  9. data: 请求主体,get下不起作用
  10. timeout: 同上
  11. withCredentials: 允许携带资源凭证
  12. responseType: 响应主体信息的类型
  13. xsrfCookieName: 同上
  14. xsrfHeaderName: 同上
  15. onUploadProgress(): 监听上传的进度,传递一个事件对象
  16. onDownloadProgress(): 监听下载的进度,也会传递一个事件对象
  17. maxContentLength: 同上
  18. maxBodyLength: 同上
  19. validateStatus(): 同上
  20. cancelToken(): 同上
axios({
    baseURL: "http://127.0.0.1:8888",
    url:"/user/list",
    method:"get",
    params:{
        lx:1,
        name:"小王"
    },
    data:{
        // post系列请求才起作用
        // ...请求主体信息
        // 数据格式可以是以下几种:
        // 1. raw(默认的时json):json,text,xml...
        // 2. x-www-form-urlencoded: 'lx=xx&name=xx'的格式
        // 3. form-data:文件上传或者表单
        // 4. binary:进制流格式,多用于大文件上传
    },
    headers:{
        // ...请求头
    },
    transformRequest(data, headers){
        // ...进行数据转换
    },
    timeout: 0,
    validateStatus(status){
        // 对状态码进行处理,返回true,axios才能继续走下去
    }
})

// 快捷方法
axios.get("http://127.0.0.1:8888/user/list",{
    params:{
        lx:1,
        name:"小王"
    },
    headers:{
        // ...请求头
    },
})

axios.post("http://127.0.0.1:8888/user/list",{
    // 传递的data数据,请求主体信息
},{
    params:{
        lx:1,
        name:"小王"
    },
    headers:{
        // ...请求头
    },
})

axios响应成功的信息

  1. config: 请求的配置信息
  2. data: 后端返回的信息(一般会进行二次封装将这个信息直接返回)
  3. headers: 响应头信息
  4. request: 发送的原生ajax信息
  5. status: http响应状态码
  6. statusText: http状态码的信息

axios响应失败的信息

  1. resopnse: 失败的响应信息:当请求中断、超时或者断网时值为undefined
    • 和响应成功的信息一样,只是值不一样
  2. config: 请求的配置项
  3. isAxiosError: 是否为axios错误
  4. request: 原生ajax实例对象
  5. toJSON(): 转换JSON方法
  6. message: 错误的信息
  7. code: 'ECONNABORTED',当超时或者被中断的时候出现

axios自己取消请求CancelToken

const CancelToken = axios.CancelToken;
const source = CancelToken.source();

axios.get('/user/12345', {
  cancelToken: source.token
}).catch(function(thrown) {
  if (axios.isCancel(thrown)) {
    console.log('Request canceled', thrown.essage);
  } else {
     // 处理错误
  }
});

axios.post('/user/12345', {
  name: 'new name'
}, {
  cancelToken: source.token
})

// 取消请求(message 参数是可选的)传递给错误信息的message
source.cancel('Operation canceled by the user.');

封装axios

在项目中,有很多的接口都有统一的配置,这个时候提取出来提前配置好能缩短开发周期,更快捷的开发。

  1. baseURl
  2. headers
  3. transformRequest()
  4. timeout
  5. withCredentials
  6. validateStatus()
  7. interceptors.request()
  8. interceptors.response()
/* 
    axios的二次封装,将常用的公共配置项提前配置好,对响应内容做统一处理
 */


/* 
    baseURL: 在项目中通过环境变量来进行区分(node中的环境变量),不同环境使用不同的服务器
    + 开发 development
    + 测试 test
    + 灰度 gray(一般在上线很重要的功能是会存在一个灰度环境,其目的是慢慢的将用户转移,防止全部转移出现重大bug难以承受,如果转移的没问题在慢慢进行转移)
    + 生产 production
*/
// let env = process.env.NODE_ENV || "development";
// switch (env) {
//     case "development":
//         axios.defaults.baseURl = "http://127.0.0.1:8888";
//         break;
//     case "test":
//         axios.defaults.baseURl = "http://api.test:8888";
//         break;
//     case "development":
//         axios.defaults.baseURl = "http://api:8888";
//         break;
// }
// 超时时间
axios.defaults.timeout = 1000;
// 允许携带资源凭证
axios.defaults.withCredentials = true;
// 校验http状态码
axios.defaults.validateStatus = (status) => {
    return status >= 200 && status < 400;
}
/* 
    设置请求头 
    + headers[xx]=xx 直接给设置请求头
    + headers.common[xx]=xx 存在common,会默认给每个请求加上请求头
    + headers.post/get[xx]=xx 对应请求的请求头走这里,这个会覆盖common和直接给headers写
*/
// 对于Content-Type这个特殊的请求头来说,@1这个比重比@2@3common/post/get...重,
// 仅仅比直接写配置项低一点,也就是可以将请求头强制改变为这个,
// 而其他的也设置了这样的效果,但是axios还是会根据所传递的参数去给Content-Type赋值
axios.defaults.headers["Content-Type"] = "a"; // @1
axios.defaults.headers.common["Content-Type"] = "b"; // @2
axios.defaults.headers.post["Content-Type"] = "application/x-www-form-urlencoded"; // @3

// 而对于那些没有特殊性的请求头的话直接就可以设置上去
axios.defaults.headers.get["Authorization"] = "c";
axios.defaults.headers.post["Authorization"] = "a";

// 设置请求前的数据格式处理
axios.defaults.transformRequest = (data, headers) => {
    if (data === null || typeof data !== "object") return data;

    // 获取请求类型,将数据转换
    let contentType = headers["Content-Type"] || headers.post["Content-Type"] || headers.common["Content-Type"];
    if (contentType.includes("urlencoded")) return Qs.stringify(data);
    if (contentType.includes("json")) return JSON.stringify(data);
    return data;
}

// 请求拦截器
axios.interceptors.request.use((config) => {
    // 一般在这里做携带token做身份校验
    return config;
})

// 相应拦截器
axios.interceptors.response.use((result) => {
    return result.data;
}, (reason) => {
    let response = reason.response;
    if (response) {
        // 说明服务器有返回,但是状态码校验没通过
        switch (response.status) {
            case "404":
                // 做相应的提示
                break;
        }
    } else {
        if (reason.code == "ECONNABORTED") {
            // 说明请求被中断或者超时
        }
        if (!navigator.onLine) {
            // 说明断网了,做断网提示
        }
    }
    //因为还要向下传递,所以返回失败的promise实例
    return Promise.reject(reason);
})


在接口的很多配置都差不多的情况下只是用axios来配置可以(100个接口有90多个是一样的配置,其他的在请求的时候自己加上不同的配置把默认的覆盖就行了) 但是如果100个请求有一半使用相同的,另一半使用另外一副相同的配置,这个时候可以通过axios.create创建实例来进行分开设置默认配置

let instance_1 = axios.create();
instance_1.defaults.xxx=xxx;
export default instance_1

let instance_2 = axios.create();
instance_2.defaults.xxx=xxx;
export default instance_2

axios的请求失败

  1. 网络层面的失败:断网,导致没有完成一个http事务;
  2. axios层面的失败:完成了http事务,请求有返回,但是可能校验没通过;或者是请求中断和超时;
  3. 业务层面的失败:一般返回信息都有一个code标识,可以根据这个判断是否成功获取道数据。