axios简单封装

144 阅读3分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动

axios简单封装

一、前言

之前开发的时候都是需要发送请求的时候直接调用axios的静态方法,一些配置项就会重复地配置,显得代码非常冗余。实习的时候公司对于axios进行了一层封装,可以让代码更简洁一点,也便于维护。这篇文章主要就介绍axios简单封装的方法。当然封装的方法非常多,选择合适的就好了。

二、结构

大致分为了3个模块

 - http/
     -index.js
     -request.js
     -resCodehandler.js

1. index.js

主要是将封装好的模块导出

// index.js

/**
 * @description: 通用请求模块封装
 */

import axios from 'axios';
import request from './request';

export { axios, request };
export default request;

2. request.js

主要的功能:

  1. 创建axios实例
  2. 可复用的配置项
  3. 自定义请求和响应拦截器
  4. 导出axios实例

这里可以在响应拦截器中对业务逻辑作进一步的判断。

// request.js

import axios from 'axios'
import qs from 'qs'
import resCodehandler from './resCodehandler'

// create an axios instance with a custom config
const service = axios.create({
  baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url
  timeout: 5000, // request timeout
  headers: {
    "Content-Type": "application/x-www-form-urlencoded;charset=utf-8",
    // "Content-Type": "application/json;charset=utf-8",
    // 'X-Custom-Header': 'foobar'
  }, // The custom headers

  transformRequest: [function (data, headers) {
    // Do whatever you want to transform the data
    console.log(headers)
    data = qs.stringify(data); // 使用工具qs来处理参数,处理发送请求的参数,序列化字符串
    return data;
  }],

  transformResponse: [function (data) {
    // Do whatever you want to transform the data
    return data;
  }],
})

const requestHandler = config => {
  // do something before request is sent

  config.headers['token'] = `admin token`
  config.headers['appCode'] = `appCode` // The custom headers

  return config
}

const requestErrHandler = error => {
  // do something with request error

  console.log(`error : ${error}`) // for debug
  return Promise.reject(error)
}

const responseHandler = response => {
  // Do something with response data

  const res = response.data

  // if the custom code is not Logically correct, it is judged as an error.
  // 在这里可以对response进行业务上的逻辑判断,具体逻辑可以自定义。
  if (res.code && res.code !== 20000) {

    // 通过Promise.reject方法,返回值会被认为是error处理
    return Promise.reject(new Error(res.message || 'Error'))
  }

  // 可以自定义返回的数据,比如可以只返回res
  return response
}


const responseErrHandler = error => {
  // Do something with response error

  resCodehandler(error);

  console.log(`error : ${error}`) // for debug
  return Promise.reject(error)
}


// Add a request interceptor
service.interceptors.request.use(requestHandler, requestErrHandler)

// Add a response interceptor
service.interceptors.response.use(responseHandler, responseErrHandler
)

export default service



3. resCodehandler.js

主要的功能:

  1. 自定义错误处理 主要包括控制逻辑业务逻辑的错误。

这里也可能存在控制逻辑为正常,但业务逻辑不正常的情况。比如采用两级状态码(HTTP状态码,业务状态码),这样就需要更细化区分不同的情况做出处理。


import { Message } from "element-plus";
import router from '../../router'

const CODE_MESSAGE = {
    200: '服务器成功返回请求数据',
    201: '新建或修改数据成功',
    202: '一个请求已经进入后台排队(异步任务)',
    204: '删除数据成功',
    400: '发出信息有误',
    401: '用户没有权限(令牌、用户名、密码错误)',
    403: '用户得到授权,但是访问是被禁止的',
    404: '访问资源不存在',
    406: '请求格式不可得',
    410: '请求资源被永久删除,且不会被看到',
    500: '服务器发生错误',
    502: '网关错误',
    503: '服务不可用,服务器暂时过载或维护',
    504: '网关超时',
};

// 提示语可以传入也可以匹配默认值
const info = function (status, MESSAGE = CODE_MESSAGE[`${status}`]) {
    return Message({
        showClose: true,
        message: `${MESSAGE}`,
        type: "error",
        duration: "5000"
    });
}

const resCodehandler = function (res) {
    switch (res.status) {
        case 400: {
            info(res.status)
            break
        }
        case 401: {
            //对于相同的HTTP状态码,如果业务还需要细分,可以再添加一个属性来区分
            if ([118000014, 118000015, 118000016].includes(res.code)) {
                router.replace({
                    path: '/login',
                    query: {
                        redirect: router.currentRoute.fullPath
                    }
                });
            }
            break;
        }

        // 403 比如token过期                          
        case 403: {
            info(res.status)

            localStorage.removeItem('token');
            router.replace({
                path: '/login',
                query: {
                    redirect: router.currentRoute.fullPath
                }
            });
            break
        }
        case 404: {
            info(res.status)

            // 也可以自定义页面
            // router.push({
            //     path: "/error/404"
            // });
            break
        }
        case 406: {
            info(res.status)
            break
        }
        case 500: {
            info(res.status)
            break
        }
        case 502: {
            info(res.status)
            break
        }
        case 503: {
            info(res.status)
            break
        }
        case 504: {
            info(res.status)
            break
        }
        default:{
            info(res.status,'未知错误')
            break
        }
    }
}

export {
    resCodehandler
}

三、用法

  1. 先引入request模块
  2. 然后调用即可

import request from "../utils/http";

export const init_get = data => {
    return request({
        url: `http://localhost:3000/posts/${data}`,
        method: "get",
    })
}

export const init_post = data => {
    return request({
        url: "http://localhost:3000/posts",
        method: "post",
        data: {
            title: "今天天气不错, 还挺风和日丽的",
            author: "Alice"
        }||data
    })
}