axios在企业级vue项目中的应用(附带axios正确打开方式)

在一个大型的vue项目中,需要编写请求接口实在太多太多了,如果每一个接口都从创建实例开始,那代码将会相当庞大以及十分臃肿,后期很难维护,那我们来看看企业级项目中,http请求是怎么抽离出来的吧。

在这里插入图片描述
首先是request.js,这个文件是用来处理axios的配置、设置拦截器等等,它创建了一个实例,并将这个实例导出。代码如下,注释都写在里面啦

import Vue from 'vue'
import axios from 'axios'
// 创建 axios 实例
const service = axios.create({
  baseURL: '/user', // 基础地址
  timeout: 6000 // 请求超时时间
})

/**
 * 请求拦截器,携带每个请求的token(可选) 
 */
service.interceptors.request.use(config => {
  const token = Vue.ls.get("ACCESS_TOKEN") //token是放在vuex中的state中
  if (token) {
    config.headers['X-Access-Token'] = token // 让每个请求携带自定义 token 请根据实际情况自行修改
  }
  if (config.method == 'get') {
    config.params = {
      _t: Date.parse(new Date()) / 1000, //让每个请求都携带一个不同的时间参数,防止浏览器缓存不发送请求
      ...config.params
    }
  }
  return config
}, (error) => {
  return Promise.reject(error)
})

/**
 * 响应拦截器中的error错误处理
 */
const err = (error) => {
  if (error.response) {
    switch (error.response.status) {
      case 401:
        console.log({
          message: '系统提示',
          description: '未授权,请重新登录',
          duration: 4
        })
        break
      case 403:
        console.log({
          message: '系统提示',
          description: '拒绝访问'
        })
        break

      case 404:
        console.log({
          message: '系统提示',
          description: '很抱歉,资源未找到!',
          duration: 4
        })
        break
      case 500:
        console.log({
          message: '系统提示',
          description: 'Token失效,请重新登录!'
        })
        break
      case 504:
        console.log({
          message: '系统提示',
          description: '网络超时'
        })
        break
      default:
        console.log({
          message: '系统提示',
          description: error.response.data.message,
        })
        break
    }
  }
  return Promise.reject(error)
};

/**
 * 响应拦截器,将响应中的token取出,放到state中
 */
service.interceptors.response.use((response) => {
  const token = response.headers["authorization"]
  if (token) {
    Vue.ls.set("ACCESS_TOKEN", token) //token是放在vuex中的state中
  }
  return response.data
}, err)

export {
  service as axios
}

第二个便是manage.js,这个文件主要是书写不同的http请求,getpost等,在请求中配置某些特殊的配置

import { axios } from './request'

//get
export function getAction(url,params) {
  return axios({
    url: url,
    method: 'get',
    params: params
  })
}
//post
export function postAction(url,data) {
  return axios({
    url: url,
    method:'post' ,
    data: data
  })
}

//put
export function putAction(url,data) {
  return axios({
    url: url,
    method:'put',
    data: data
  })
}

//deleteAction
export function deleteAction(url,params) {
  return axios({
    url: url,
    method: 'delete',
    params: params
  })
}

/**
 * 下载文件
 * @param {*} url: 请求地址
 * @param {*} params: 请求参数
 */
export function downFileAction(url,params){
  return axios({
    url: url,
    params: params,
    method:'get' ,
    responseType: 'blob'
  })
}
/**
 * 用于上传文件
 * @param {*} url:请求地址
 * @param {*} data:请求体数据
 */
export function fileUploadAction(url,data){
  return axios({
    url: url,
    data: data,
    method:'post' ,
    headers:{
      'Content-Type':'multipart/form-data'
    },
    timeout:1000*60*4  //上传时间4分钟
  })
}

最后这个api.js文件就是我们需要写的接口了,把接口都写在一个文件中,也是为了方便我们维护,在使用的时候,导入使用便可

import { getAction,deleteAction,putAction,postAction,downFileAction,fileUploadAction} from '@/api/manage'

const getTest = (params)=>getAction("/api/user/get",params);
const deleteActionTest = (params)=>deleteAction("/api/user/delete",params);
const putActionTest = (params)=>putAction("/api/user/put",params);
const postActionTest = (params)=>postAction("/api/user/post",params);
const downFileActionTest = (params)=>downFileAction("/api/user/downfile",params);
const fileUploadActionTest = (params)=>fileUploadAction("/api/user/fileupload",params);


export {
  getTest,
  deleteActionTest,
  putActionTest,
  postActionTest,
  downFileActionTest,
  fileUploadActionTest
}

附带一个项目中用到的文件下载链接处理

axios.get("/api/excel",{id:'001'}).then(res=>{//返回的数据是二进制文件流
    var blob = new Blob([res],{type: 'application/force-download;charset=utf-8'});
    var downloadElement = document.createElement('a');
    var href = window.URL.createObjectURL(blob); //创建下载的链接
    downloadElement.href = href;
    downloadElement.download = 'name.xls'; //下载后文件名
    document.body.appendChild(downloadElement);
    downloadElement.click(); //点击下载
    document.body.removeChild(downloadElement); //下载完成移除元素
    window.URL.revokeObjectURL(href); //释放掉blob对象 
  })

axios的正确打开方式

axios是一个基于promise的HTTP库,目前已经被主流浏览器其支持(Chrome、Firefox、Safari、Opera、Edge、IE8+)

我们先来举个例子:

<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app">
    {{ name }}
</div>
<script>
    const vm = new Vue({
        el: "#app",
        data: {
            name: "monk"
        },
        created() {
            axios("https://xxxx").then(res=>{
                console.log(res)
            })
        }
    })
</script>

从这个例子就可以看出来,axios的使用非常简单,我们首先需要引入axios,然后直接使用就可以了,axios有两种写法(2个API),一个是例子所示:axios(url, [config]),另一个是:axios(config)config是一个配置对象。我在下面会介绍如何引入和如何配置axios

引入方式可以使用cnd引入

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

也可以使用npm下载后使用

$ npm install axios
import axios from 'axios'

使用axios

我们使用axios,我总结了三种方式

扫描二维码关注公众号,回复: 10397730 查看本文章

1、简单粗暴直接使用axios

axios("https://xxxx",{
    method:"get"
}).then(res=>{
    console.log(res)
})

2、使用axios请求方法的别名,在使用别名方法时 urlmethoddata 这些属性都不必在配置中指定。

axios.get("https://xxxx").then(res=>{
    console.log(res)
})
//这里所有的请求方法都有别名
axios.request(config)
axios.get(url[, config])
axios.delete(url[, config])
axios.head(url[, config])
axios.post(url[, data[, config]])
axios.put(url[, data[, config]])
axios.patch(url[, data[, config]])

3、创建axios实例,实例上的方法和请求别名相同

const service = axios.create()
service.get("https://monk/api/getUserInfo").then(res=>{
    console.log(res)
})

axios配置

我再简单列举一下axios常用的配置

{
  url: "", // 用于请求的服务器的地址
  method: 'get', // 请求时使用的方法,默认是 get
  baseURL: 'https://monk/api/', //baseURL将自动加在url前面
  headers: {},//定义请求头的信息
  params: {}, // 将与请求一起发送的 URL 参数,会拼接在url后面
  data: {},  //会将请求参数放在请求体中
  timeout: 1000, //请求超时的毫秒数,超出时间后,请求就会被中断
  responseType: 'json', // 默认是json,表示服务器响应的数据类型,可以是 'arraybuffer', 'blob', 'document', 'json', 'text', 'stream'
}

在对axios进行配置时可以从三个方面进行配置,全局上配置,实例上配置,请求上配置,他们也是有优先级的,请求配置>实例配置>全局配置,我来依次介绍一下:

  • 全局配置:但是我们在实际的项目中,很少使用全局配置
axios.defaults.baseURL = 'https://www.monk.com/api';
axios.defaults.timeout = 1000;
  • 实例配置:实力上配置,首先就是要创建一个实例了
const service = axios.create({
  baseURL: 'https://www.monk.com/api',
  timeout: 1000,
})
service.get('/getUserInfo').then(res => {
  console.log(res)
})
  • 请求配置:在请求中配置的优先级最大。
const instance = axios.create();
instance.get('https://www.monk.com/api/fileupload', {
  timeout: 5000
})

当然,我们也可以混合使用:在普通的请求超时1s,在上传文件时,我们超时5s才阻止请求

const service = axios.create({
  baseURL: 'https://www.monk.com/api',
  timeout: 1000,
})
service.get('/fileupload', {
  timeout: 5000
}).then(res => {
  console.log(res)
})

下面我们再来讲解一下并发请求,虽然一般用不到

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

  • axios.all(iterable)iterable为需要并发的请求
  • axios.spread(callback)callback是每个请求的回调
const service = axios.create({
  baseURL: 'https://www.monk.com/api',
  timeout: 1000,
})
service.all([
  axios.get('/a'),
  axios.get('/b')
]).then(axios.spread((aRes, bRes) => {
  console.log(aRes, bRes);
}))

上述代码是并发执行请求/a/b,当请求结束时,在Promise中执行的回调时spread方法,依次调用里面的回调函数。

拦截器

在axios中,拦截器是非常重要的一个部分,那么什么是拦截器呢?

拦截器interceptors,在发起请求之前做一些处理,或在响应回来之后做一些处理。

在这里插入图片描述

  • 请求拦截器
axios.interceptors.request.use(function (config) {
    // 在发送请求之前做些什么
    return config;
  }, function (error) {
    // 对请求错误做些什么
    return Promise.reject(error);
  })
  • 响应拦截器
axios.interceptors.response.use(function (response) {
    // 对响应数据做点什么
    return response;
  }, function (error) {
    // 对响应错误做点什么
    return Promise.reject(error);
  })
  • 移除拦截器
const myInterceptor = axios.interceptors.request.use(config => {});
axios.interceptors.request.eject(myInterceptor);
  • axios实例添加拦截器
const service = axios.create();
service.interceptors.request.use(config => {
    //...
    return config
});

错误处理

在请求错误时进行的处理,error中有两个属性(上下文),request 和response,在错误中,如果响应有值,说明响应时出现了错误,如果响应没用值,则说明请求出现了错误,如果请求没用值,则说明请求未发出去,比如请求被取消。

axios.get('https:/monk/api/user')
.catch(function (error) {
    // 错误可能是请求错误,也可能是响应错误
    if (error.response) {
        // 响应错误
        console.log(error.response)
    } else if (error.request) {
        // 请求错误
        console.log(error.request)
    } else {
        console.log('Error', error.message);
    }
});

在实际开发过程中,一般在拦截器中统一添加错误处理,请求拦截器中的错误,会当请求未成功发出时执行,但是要注意的是:取消请求后,请求拦截器的错误函数也不会执行,因为取消请求不会抛出异常,axios对其进行了单独的处理。在更多的情况下,我们会在响应拦截器中处理错误。

const instance = axios.create({});
instance.interceptors.request(config => {
	//....
}, error => {
    //错误处理
  return Promise.reject(error);
})

instance.interceptors.response(response => {
	//....
}, error => {
    //错误处理
  return Promise.reject(error);
})

axios 预检

当axios的请求为非简单请求时,浏览器会进行预检,及发送OPTIONS请求。请求到服务器,询问是否允许跨域。如果响应中允许预检中请求的跨域行为,则浏览器会进行真正的请求。否则会报405错误。

响应结构

最后再附带一个axios响应的结构

{
  data: {}, //由服务器提供的响应

  status: 200, //来自服务器响应的 HTTP 状态码

  statusText: 'OK', //来自服务器响应的 HTTP 状态信息

  headers: {}, //服务器响应的头

  config: {}  // 是为请求提供的配置信息
}
发布了33 篇原创文章 · 获赞 105 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/Newbie___/article/details/105238226