二次封装axios?有手就行


前言

Axios相信对前端熟悉的同学对它不会感到陌生了,这简直就是前端近年来的一大杀器,
官方推荐使用axios来进行网络请求,后面基本大部分项目都能瞧见它的身影。虽然axios很强,
但是单纯的axios并不能满足我们日常的使用,因此很多时候我们都需要对axios进行二次封装,
接下来我们就来详细讨论讨论。

为什么要二次封装axios

通常我们的项目会越做越大,页面也会越来越多,如果页面非常的少,直接用axios也没有什么大的影响,
那页面组件多了起来,上百个接口呢,这个时候后端改了接口,多加了一个参数什么的呢?那就只有找到那个页面,
进去修改.整个过程很繁琐不易于项目的维护和迭代.
这个时候如果我们统一的区管理接口,需要修改某一个接口的时候直接在api里修改对应的请求是不是很方便呢?
总结:api统一管理,不管接口有多少,所有的接口都可以非常清晰,容易维护.

初始化项目

yarn create vite

这里我们使用vite来初始化一个Vue项目

下载axios

yarn add axios

独立管理api接口

以图灵官网的接口为例
我们在项目中创建 api文件夹用来管理所有的API,创建axios.js 文件二次封装axios.

//axios.js
import axios from "axios";

function myAxios(axiosConfig) {
    const service = axios.create({
        baseURL: "https://www.turingteam.me:8081", // 设置统一的请求前缀
        timeout: 10000 // 设置统一的超时时长
    });

    return service(axiosConfig);
}

export default myAxios

这里的service(axiosConfig)返回的是一个Promise对象

编写不同功能的api

如所有成员相关的API就放在 member.js 文件中,所有项目相关的API就放在 project.js 中,
这样子就很有条理性。
下面我们来 project.js 中编写获取项目列表的API。

//project.js
import myAxios from "../axios";

//团队项目查询
export function queryProjectAPI(offset, page) {
    return myAxios({
        url: "/guest/project/queryProject",
        method: 'get',
        params: {
            offset,
            page
        }
    })
}

//通过id查询团队项目详细信息
export function queryProjectByIdAPI(id) {
    return myAxios({
        url: "/guest/project/queryProjectById",
        method: 'get',
        params: {
            id
        }
    })
}

在页面中具体使用

在 App.vue 文件中随便加一个按钮,点击触发请求。

<template>
  <button @click="getList">点击</button>
</template>

<script lang='js'>
import {defineComponent} from 'vue'
import {queryProjectAPI} from '@/api/project.js';
export default defineComponent({
  setup() { 
   const getList = async () => {
     try{
        let res = await queryProjectAPI(offset, page)
        console.log(res);
     }catch(error){
        console.log(error);
     }

    }

    return {
      getList
    }
  }
})
</script>

到此,我们就封装了一个最简单的axios,我们每次新增加一个 API,只需要找到对应模块的 API 文件去添加即可,然后再到具体页面导入使用

POST请求参数序列化

在POST请求中的 Content-Type 常见的有以下3种形式:

Content-Type: application/json
Content-Type: application/x-www-form-urlencoded
Content-Type: multipart/form-data

现在主流基本在用application/json形式,Axios默认以这种形式工作,我们给后端接口传递参数也简单,直接丢在其data参数就行了。
我们在 resume.js 文件中编写简历API

import myAxios from "../axios";


//创新组内容填写
export function resumeInnovateAddAPI(data) {
    return myAxios({
        url: "/guest/resume/resumeInnovateAdd",
        method: 'post',
        data: data,
  });
}

但是有时候后端要求Content-Type必须以application/x-www-form-urlencoded形式,那么通过上面传递的参数,后端是收不到的,我们必须对参数数据进行所谓的序列化处理才行,让它以普通表单形式(键值对)发送到后端,而不是json形式

import myAxios from "../axios";

//创新组内容填写
export function resumeInnovateAddAPI(data) {
    return myAxios({
        url: "/guest/resume/resumeInnovateAdd",
        method: 'post',
        data: data,
        headers: {
      'Content-Type': 'application/x-www-form-urlencoded'
    },
    transformRequest: [
      (data) => {
        let result = ''
        for (let key in data) {
          result += encodeURIComponent(key) + '=' + encodeURIComponent(data[key]) + '&'
        }
        return result.slice(0, result.length - 1)
      }
    ],
}

我通过 headers 来指定Content-Type的形式,对于 transformRequest 就是允许在向服务器发送前,修改请求数据,但只能用在 ‘PUT’,’POST’ 和 ‘PATCH’ 这几个请求方法,且后面数组中的函数必须返回一个字符串,或 ArrayBuffer,或 Stream,更多的还有 transformResponse 能在传递给 then/catch 前,允许修改响应数据,其余更多参数的可以去 Axios文档查看。

请求拦截器&响应拦截器

1 请求拦截器

在请求发送前进行必要操作处理,例如添加统一cookie、请求体加验证、设置请求头等,相当于是对每个接口里相同操作的一个封装;

service.interceptors.request.use(function (config) {
    // 在发送请求之前做些什么,例如加入token
    .......
    return config;
  }, function (error) {
    // 对请求错误做些什么
    return Promise.reject(error);
  });

2 响应拦截器

同理,响应拦截器也是如此功能,只是在请求得到响应之后,对响应体的一些处理,通常是数据统一处理等,也常来判断登录失效等。

service.interceptors.response.use(function (response) {
    // 在接收响应做些什么
    ......
    return response;
  }, function (error) {
    // 对响应错误做点什么
    return Promise.reject(error);
  });

未完待续


文章作者: TOBY
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 TOBY !
评论
  目录