Axios介绍

1、Axios是什么?

  • Axios是一个基于promise的HTTP库,类似于jQuery的ajax,用于http请求。可以应用于浏览器端和node.js,既可以用于客户端,也可以用于node.js编写的服务端。

2、Axios特性

  • (1)支持Promise API
  • (2)拦截请求与响应,比如:在请求前添加授权和响应前做一些事情。
  • (3)转换请求数据和响应数据,比如:进行请求加密或者响应数据加密。
  • (4)取消请求
  • (5)自动转换JSON数据
  • (6)客户端支持防御XSRF

3、浏览器支持情况

  • Firefox、Chrome、Safari、Opera、Edge、IE8+

Axios使用

vue创建项目 vue create axios-vue,选择自定义配置manually select features,终端显示如下:上下键切换,空格键选择对应配置。

axios兼容ie8吗 axios ie_前端


而后,我们一次选择一下配置:

axios兼容ie8吗 axios ie_javascript_02


运行终端指令 cd axios-vue 、npm run serve启动项目后,运行终端指令npm add axios安装axios,至此,项目创建完成,axios安装完成。

在项目的public文件夹下新建data.json文件,用于模拟数据。在组建中引入axios,并发起请求。

{
    "title":"vue project",
    "create_time":"2019-01-01"
}

在组件中中,引入axios并使用。

import axios from "axios"
 
 
axios.get("/data.json").then(res=>{
    console.log(res)
}).catch(err=>{
    console.log(err)
})

此时,已经可以请求掉数据了,效果如下:

axios兼容ie8吗 axios ie_javascript_03

axios常用的请求方法

方法列举:get, post, put, patch, delete

  • get:一般用户获取数据
  • post:一般用于表单提交与文件上传
  • patch:更新数据(只将修改的数据推送到后端)
  • put:更新数据(所有数据推送到服务端)
  • delete:删除数据

备注:post一般用于新建数据,put一般用于更新数据,patch一般用于数据量较大的时候的数据更新。

get方法

  • 方式一
    如果不带有参数,代码如下:
axios
      .get("/data.json")
      .then(res => {
        console.log(res);
      })
      .catch(err => {
        console.log(err);
      });

如果带有参数,代码如下:

axios
      .get("/data.json", {
        params: {
          id: 12
        }
      })
      .then(res => {
        console.log(res);
      })
      .catch(err => {
        console.log(err);
      });

此时表示,参数为id=12,最终的请求路径Request URL: http://localhost:8080/data.json?id=12

  • 方式二
    如果不带参数,代码如下:
axios({
          method:'get',
          url:'/data.json'
      }).then(res=>{
          console.log(res)
      })

如果带有参数,代码如下:

axios({
      method: "get",
      url: "/data.json",
      params:{
          id:12
      }
    }).then(res => {
      console.log(res);
    });

此时表示,参数为id=12,最终的请求路径Request URL:http://localhost:8080/data.json?id=12

浏览器控制台相关信息介绍:

  • Request URL:请求URL
  • Request Method:请求方式

post方法

post请求常用的数据请求格式有两种:

form-data(常用于表单提交(图片上传、文件上传))

let data = {
      id: 12
    };
    let formData = new FormData();
    for(let key in data){
      formData.append(key,data[key])
    }
    console.log(formData)
    axios.post('/data.json',formData).then(res=>{
      console.log(res,'formData')
    })

注意:请求地址Request URL: http://192.168.1.106:8080/data.json,

请求头中Content-Type: multipart/form-data; boundary=----WebKitFormBoundarydgohzXGsZdFwS16Y

参数形式:id:12

application/json(常用)
  • 方式一
let data = {
      id: 12
    };
    axios.post("/data.json", data).then(res=>{
      console.log(res, 'post')
    });
  • 方式二
let data = {
      id: 12
    };
    axios({
      method:'post',
      url:'/data.json',
      data:data
    }).then(res=>{
      console.log(res)
    })

注意:请求地址Request URL: http://192.168.1.106:8080/data.json,

请求头中Content-Type: application/json;charset=UTF-8

参数形式:{id:12}

put方法

let data = {
  id: 12
};
axios.put("/data.json", data).then(res=>{
  console.log(res, 'put')
});

patch方法

let data = {
  id: 12
};
axios.patch("/data.json", data).then(res=>{
  console.log(res, 'patch')
});

备注:put与patch与post方法只有method不同,其他相同。

delete方法

  • 方式一:params
axios
  .delete("/data.json", {
    params: {
      id: 12
    }
  })
  .then(res => {
    console.log(res, "delete");
  });
  
let params = {
  id: 12
};
axios({
  method:'delete',
  url:'/data.json',
  params:params
}).then(res=>{
  console.log(res)
})
  • 方式二:data
axios
  .delete("/data.json", {
    data: {
      id: 12
    }
  })
  .then(res => {
    console.log(res, "delete");
  });
  
let data = {
  id: 12
};
axios({
  method:'delete',
  url:'/data.json',
  data:data
}).then(res=>{
  console.log(res)
})

注意:params方式会将请求参数拼接在URL上面,Request URL: http://192.168.1.106:8080/data.json?id=12

参数形式:id:12

Content-Type: text/html; charset=utf-8

data方式不会讲参数拼接,是直接放置在请求体中的,Request URL:http://192.168.1.106:8080/data.json

参数形式:{id:12}

Content-Type: application/json;charset=UTF-8

总结:上述方法中均对应两种写法:(1)使用别名:形如axios.get();(2)不使用别名形如axios();

并发请求

并发请求,就是同时进行多个请求,并统一处理返回值。

在例子中,我们使用axios.all,对data.json/city.json同时进行请求,使用axios.spread,对返回的结果分别进行处理。代码如下:

// 并发请求
axios.all([axios.get("/data.json"), axios.get("/city.json")]).then(
  axios.spread((dataRes, cityRes) => {
    console.log(dataRes, cityRes);
  })
);

注意:axios.all的参数是请求函数的数组,在对应的回调then中,调用axios.spead对返回值进行处理,即可。

并发请求的应用场景:需要同时进行多个请求,并且需要同时处理接口调用的返回值的时候,我们可以使用并发请求。

axios实例的创建

比如:后端接口地址有多个(www.test.com、www.example.com),并且超时时长不同(1000ms、2000ms),这个时候,我们可以创建实例。

思路如下:创建多个实例,配置不同的超时时长,用不同的实例去请求不同的接口。使用axios.acreate来创建实例,配置相关信息,进行网络请求。代码如下:

// 实例1
let instance = axios.create({
  baseURL:'http://loacalhost:8080',
  timeout:1000
})
instance.get('/data.json').then(res=>{
  console.log(res)
})
//实例2
let instance2 = axios.create({
  baseURL: "http://loacalhost:8081",
  timeout: 2000
});
instance2.get("/city.json").then(res => {
  console.log(res);
});

备注:此时我们就可以访问http://loacalhost:8080与http://loacalhost:8081两个不同域名的接口,并且使用不同的配置。

axios实例的相关配置

(1)配置列表

  • baseURL:请求的域名(基本地址)。
  • timeout:请求的超时时长,超出后后端返回401。
  • 备注:一般由后端定义,后端的接口需要的处理时长较长的时候,如果请求的时间过长,后端处理不过来,就会阻塞,给服务器造成较大的压力。设置后,可以及时释放掉。
  • url:请求路径。
  • method:请求方法。如:get、post、put、patch、delete等。
  • headers:请求头。
  • params:将请求参数拼接到url上
  • data:将请求参数放置到请求体里
axios.create({
        baseURL:'', //请求的域名(基本地址)
        timeout:2000, //请求的超时时长,单位毫秒,默认。
        url:'/data.json', //请求路径
        method:'get', //请求方法
        headers:{
            token:''
        }, //设置请求头
        params:{

        },//将请求参数拼接到url上
        data:{

        }, //将请求参数放置到请求体里
    });

三种配置方式:

  • axios全局配置
axios.defaults.baseURL = 'http://localhost:8080'
    axios.defaults.timeout = 2000
  • axios实例配置
let instance = axios.create();
    instance.defaults.timeout = 3000
  • axios请求配置
instance.get('/data.json',{
        timeout:5000
    })

优先级:axios全局配置 < axios实例配置 < axios请求配置

常用参数配置的使用方法

  • 举例1:
let instance1 = axios.create({
        baseURL:'http://localhost:9090',
        timeout:1000
    })
    instance1.get("/contactList",{
        params:{
            id:10
        }
    }).then(res=>{
        console.log(res)
    })

分析:配置的参数为baseURL:‘http://localhost:9090’,timeout:1000,method:‘get’,params:{ id:10},url:’/contactList’

  • 举例2:
let instance2 = axios.create({
        baseURL:'http://localhost:9091',
        timeout:3000
    })
    instance2.get("/contactList",{
        timeout:5000
    }).then(res=>{
        console.log(res)
    })

分析:配置的参数为baseURL:‘http://localhost:9091’,timeout:5000,method:‘get’,url:’/contactList’

注意:最终的有效配置是由优先级高的覆盖优先级低的。

拦截器

什么拦截器?

在请求前或响应被处理前拦截他们,分为两种:请求拦截器与响应拦截器

拦截器的使用方法

  • 请求拦截器
//   请求拦截器
    axios.interceptors.request.use(config => {
      // 在发送请求前做些什么
      return config;
    }, err=>{
        // 在请求错误的时候的逻辑处理
        return Promise.reject(err)
    });
  • 响应拦截器
// 响应拦截器
    axios.interceptors.response.use(res => {
      // 在请求成功后的数据处理
      return res;
    }, err=>{
        // 在响应错误的时候的逻辑处理
        return Promise.reject(err)
    });
  • 取消拦截器
let inter = axios.interceptors.request.use(config=>{
        config.header={
            auth:true
        }
        return config
    })
    axios.interceptors.request.eject(inter)

实用举例A:登录权限

需要token的接口实例
// 需要token的接口
    let instance = axios.create({});
    instance.interceptors.request.use(config=>{
        config.headers.token = '';
        return config
    })
不需要token的接口实例
// 不需要token接口
    let newInstance = axios.create({});

实用举例B:移动端开发数据加载loading动画

// 请求的加载动画loading
    let instance_phone = axios.create({});
    instance_phone.interceptors.request.use(config=>{
        $('#loading').show();
        return config
    })
    instance_phone.interceptors.response.use(res=>{
        $('#loading').hide();
        return res
    })

备注:实现的效果是请求数据的时候显示loading动画,数据响应后隐藏loading动画。

错误处理

结合请求拦截器与响应拦截器来说,不管是请求错误还是响应错误,都会执行catch方法。

//  请求拦截器
    axios.interceptors.request.use(
      config => {
        // 在发送请求前做些什么
        return config;
      },
      err => {
        // 在请求错误的时候的逻辑处理
        return Promise.reject(err);
      }
    );
    // 响应拦截器
    axios.interceptors.response.use(
      res => {
        // 在请求成功后的数据处理
        return res;
      },
      err => {
        // 在响应错误的时候的逻辑处理
        return Promise.reject(err);
      }
    ); 
	axios
      .get("data.json")
      .then(res => {
        console.log(res);
      })
      .catch(err => {
        console.log(res);
      });

错误处理举例

在实际开发中,不会再每次网络请求的时候,都使用catch方法,可以添加统一的错误处理方法。代码如下:

//   请求错误处理
    let instance = axios.create({});
    instance.interceptors.request.use(
      config => {
        return config;
      },
      err => {
        // 请求错误的常见状态码:4XX  401-请求超时  404-mot found
        $("#error").show();
        setTimeout(()=>{
           $("#error").hide(); 
        }, 2000)
        return Promise.reject(err);
      }
    );
    // 响应错误处理
    instance.interceptors.response.use(
      res => {
        return res;
      },
      err => {
        // 响应错误的常见状态码 5XX 500-服务器错误 502-服务器重启
        $("#error").show();
        setTimeout(()=>{
           $("#error").hide(); 
        }, 2000)
        return Promise.reject(err);
      }
    );
    instance.get("/data.json").then(res=>{
        console.log(res,'请求成功')
    }).catch(err=>{
        console.log(err,'除了拦截器设置的处理之外的其他处理')
    })

思路分析:首先创建实例,给实例设置请求拦截器与响应拦截器。

  • (1)请求错误的常见状态码以4开头,如401-请求超时、404-接口未找到;
  • (2)响应错误的常见状态码以5开头,如500-服务器错误、502-服务器重启等。
  • (3)处理设置请求拦截器与响应拦截器的操作外,如果还要其他操作,我们可以在请求的时候,在使用catch方法。

取消请求(不常用)

  • 代码示例
let source = axios.CancelToken.source();
    axios
      .get("/data.json", {
        cancelToken: source.token
      })
      .then(res => {
       	console.log(res);
      }).catch(err=>{
        console.log(err)
      })
    //   取消请求(参数msg)
      source.cancel('自定的的字符串可选')
  • 应用场景
    在查询数据的时候,很长时间(3-5s)仍未获取数据,这个时候需要取消请求。

代理

vue cil2
代理分为旧版本 也就是 vue cil2  这个版本需要在config/index.js下配置
dev: {
    // Paths
    assetsSubDirectory: 'static',
    assetsPublicPath: '/',
    // 后端请求地址代理,配置后testIp再之后的页面调用时就直接指代 http://197.82.15.15:8088
    proxyTable: {
      '/testIp': {
        target: 'http://197.82.15.15:8088',
        changeOrigin: true,
        pathRewrite: { 
          '^/testIp': ''
        }
      },
      '/elseIp': {
        target: 'http://182.83.19.15:8080',
        changeOrigin: true,
        pathRewrite: { 
          '^/esleIp': ''
        }
      },
    },
-----------------------------------------------------------

vue cil 3在 vue.config.js文件下

    devServer: {
            overlay: { // 让浏览器 overlay 同时显示警告和错误
              warnings: true,
              errors: true
            },
            host: "localhost",
            port: 8080, // 端口号
            https: false, // https:{type:Boolean}
            open: false, //配置后自动启动浏览器
            hotOnly: true, // 热更新
            // proxy: 'http://localhost:8080'   // 配置跨域处理,只有一个代理
            proxy: { //配置多个代理
                "/testIp": {
                    target: "http://197.0.0.1:8088",
                    changeOrigin: true,
                    ws: true,//websocket支持
                    secure: false,
                    pathRewrite: {
                        "^/testIp": "/"
                    }
                },
                "/elseIp": {
                    target: "http://197.0.0.2:8088",
                    changeOrigin: true,
                    //ws: true,//websocket支持
                    secure: false,
                    pathRewrite: {
                        "^/elseIp": "/"
                    }
                },
            }
        }
当项目有多个后台的时候,可以在api文件夹下 新建一个elseApi.js  ,书写当前ip下的接口请求。方法同上,只是 `let resquest = "/elseIp/request/"` 调用的时候把端口更改一下。

request.js

在项目src目录下新建utils文件夹,然后在其中新建 request.js文件,这个文件是主要书写axios的封装过程。 
/****   request.js   ****/
// 导入axios
import axios from 'axios'
// 使用element-ui Message做消息提醒
import { Message} from 'element-ui';
//1. 创建新的axios实例,
const service = axios.create({
  // 公共接口--webpack中的全局变量process.env.BASE_API
  //为了适应多个后台或者开发的时候的api地址和发布的时候的api地址不一样这种情况
  baseURL: process.env.BASE_API,
  // 超时时间 单位是ms,这里设置了3s的超时时间
  timeout: 3 * 1000
})
// 2.请求拦截器
service.interceptors.request.use(config => {
  //发请求前做的一些处理,数据转化,配置请求头,设置token,设置loading等,根据需求去添加
  
  
  ***** 下面详解
   config.data = JSON.stringify(config.data); //数据转化,也可以使用qs转换
   config.headers = {
     'Content-Type':'application/x-www-form-urlencoded' //配置请求头
   }
   //注意使用token的时候需要引入cookie方法或者用本地localStorage等方法,推荐js-cookie
   const token = getCookie('名称');//这里取token之前,你肯定需要先拿到token,存一下
   if(token){
      config.params = {'token':token} //如果要求携带在参数中
      config.headers.token= token; //如果要求携带在请求头中
    }
    *****
    
    
  return config
}, error => {
  Promise.reject(error)
})

// 3.响应拦截器
service.interceptors.response.use(response => {
  //接收到响应数据并成功后的一些共有的处理,关闭loading等
  
  return response
}, error => {
   /***** 接收到异常响应的处理开始 *****/
  if (error && error.response) {
    // 1.公共错误处理
    // 2.根据响应码具体处理
    switch (error.response.status) {
      case 400:
        error.message = '错误请求'
        break;
      case 401:
        error.message = '未授权,请重新登录'
        break;
      case 403:
        error.message = '拒绝访问'
        break;
      case 404:
        error.message = '请求错误,未找到该资源'
        window.location.href = "/NotFound"
        break;
      case 405:
        error.message = '请求方法未允许'
        break;
      case 408:
        error.message = '请求超时'
        break;
      case 500:
        error.message = '服务器端出错'
        break;
      case 501:
        error.message = '网络未实现'
        break;
      case 502:
        error.message = '网络错误'
        break;
      case 503:
        error.message = '服务不可用'
        break;
      case 504:
        error.message = '网络超时'
        break;
      case 505:
        error.message = 'http版本不支持该请求'
        break;
      default:
        error.message = `连接错误${error.response.status}`
    }
  } else {
    // 超时处理
    if (JSON.stringify(error).includes('timeout')) {
      Message.error('服务器响应超时,请刷新当前页')
    }
    error.message('连接服务器失败')
  }

  Message.error(error.message)
  /***** 处理结束 *****/
  //如果不需要错误处理,以上的处理过程都可省略
  return Promise.resolve(error.response)
})
//4.导入文件
export default service0

数据转换说明

config.data = JSON.stringify(config.data);
config.headers = { 'Content-Type':'application/x-www-form-urlencoded'  }
const token = getCookie('名称')
if(token){ 
  config.params = {'token':token} ; 
  config.headers.token= token; 
}

上述的代码都是请求的配置项,非必须,也是分情况的,data/headers/params 这种本身的参数都有多种,和后台沟通,需要什么就配什么!
config.data = JSON.stringify(config.data);为什么不用qs.stringify,因为我的后台想要的只是json类型的传参,而qs转换会转换成为键值对拼接的字符串形式。当然你们后台需要传递字符串类型参数,那就换成qs或者其他格式方式。
const token = getCookie('名称')这是token的取值,在取之前你肯定需要发请求拿到token,然后setCookie存起来,而名称就是你存的token的名称,每个人的不一样;
config.headers = { 'Content-Type':'application/x-www-form-urlencoded' }请求头内容的配置,也是不同的,application/x-www-form-urlencoded :form表单数据被编码为key/value格式发送到服务器(表单默认的提交数据的格式),你可以根据实际情况去配置自己需要的;
以上
我已经举了很清晰的例子,写代码的过程是自己动脑去搭建工程的,希望能看到我文章的各位,善于搜索,善于思考,善于总结;
当然我很喜欢帮大家解决问题,但是相关的基础问题,还是建议自己去学习掌握。

Axios中的http.js

在项目src目录下的utils文件夹中新建 http.js文件,这个文件是主要书写几种请求的封装过程。
/****   http.js   ****/
// 导入封装好的axios实例
import request from './request'

const http ={
    /**
     * methods: 请求
     * @param url 请求地址 
     * @param params 请求参数
     */
    get(url,params){
        const config = {
            method: 'get',
            url:url
        }
        if(params) config.params = params
        return request(config)
    },
    post(url,params){
        const config = {
            method: 'post',
            url:url
        }
        if(params) config.data = params
        return request(config)
    },
    put(url,params){
        const config = {
            method: 'put',
            url:url
        }
        if(params) config.params = params
        return request(config)
    },
    delete(url,params){
        const config = {
            method: 'delete',
            url:url
        }
        if(params) config.params = params
        return request(config)
    }
}
//导出
export default http

Axios中的api.js

在项目src目录下新建api文件夹,然后在其中新建 api.js文件,这个文件是主要书写API的封装过程。 

当一个项目中后台请求不是同一个IP地址,是多个IP地址的时候,可以在api文件夹下创建多个js文件,用来调用请求

api.js有两种导出方式,分类导出和全部导出

分类导出
import http from '../utils/http'
// 
/**
 *  @params resquest 请求地址 例如:http://197.82.15.15:8088/request/...
 *  @param '/testIp'代表vue-cil中config,index.js中配置的代理
 */
let resquest = "/testIp/request/"

// get请求
export function getListAPI(params){
    return http.get(`${resquest}/getList.json`,params)
}
// post请求
export function postFormAPI(params){
    return http.post(`${resquest}/postForm.json`,params)
}
// put 请求
export function putSomeAPI(params){
    return http.put(`${resquest}/putSome.json`,params)
}
// delete 请求
export function deleteListAPI(params){
    return http.delete(`${resquest}/deleteList.json`,params)
}

---------------------------------------------------
全部导出
import http from '../utils/http'
// 
/**
 *  @params resquest 请求地址 例如:http://197.82.15.15:8088/request/...
 *  @param '/testIp'代表vue-cil中config,index.js中配置的代理
 */
let resquest = "/testIp/request/"

// get请求
export default{
 	getListAPI(params){
    	return http.get(`${resquest}/getList.json`,params)
	},
	 postFormAPI(params){
    	return http.post(`${resquest}/postForm.json`,params)
	}
}

———————————————————————————————————————————————————
以上封装完毕接下来我们看如何调用

在Vue中调用接口

用到哪个api 就调用哪个接口——适用于上文接口分类导出;
import {getListAPI,postFormAPI, putSomeAPI, deleteListAPI} from '@/api/api'

  methods: {
      //promise调用,链式调用, getList()括号内只接受参数;
      //   get不传参
      getList() {
        getListAPI().then(res => console.log(res)).catch(err => console.log(err))
      },
		//post传参
      postForm(formData) {
        let data = formData
        postFormAPI(data).then(res => console.log(res)).catch(err => console.log(err))
      },

      //async await同步调用
      async postForm(formData) {
        const postRes = await postFormAPI(formData)
        const putRes = await putSomeAPI({data: 'putTest'})
        const deleteRes = await deleteListAPI(formData.name)
        // 数据处理
        console.log(postRes);
        console.log(putRes);
        console.log(deleteRes);
      },
   }
-----------------------------------------------

把api全部导入,然后用哪个调用哪个api——适用于全部导出

 import api from '@/api/api'
   methods: {
     getList() {
        api.getListAPI(data).then(res => {
          //数据处理
        }).catch(err => console.log(err))
      }
    }