axios的封装 及使用(vite+vue3+ts)

本文介绍了在Vite+Vue3+TS环境下如何封装axios,并提供了详细的步骤。首先通过npm安装axios,接着创建相关文件目录,如axios.ts和utils文件夹。在axios.ts中进行了基础设置和接口封装,同时利用toast组件(如element-plus或vant)进行信息提示。还创建了value-string.ts文件来定义基础地址,并讨论了element-plus的按需或完整引入。最后在index.ts中实现get和post等接口的封装,并处理接口地址的API前缀问题。

安装axios依赖  

npm i axios

在结构中创建文件目录

按照个人习惯,首先在axios.ts中引入axios(图上,代码下)

import axios from 'axios'
import { AxiosInstance } from "axios";

// 抛出一个类里面的方法
class HttpRequest {
//axios实例的类型就是AxiosInstance
  static axiosInstance: AxiosInstance;
  static init() {
    //封装代码
  }
}
export default HttpRequest.init();

 axios.ts中完整代码(下面会一个个解释)

/**
 * axios 封装
 * 请求拦截、响应拦截、错误统一处理
 */
import axios from "axios";
import { AxiosInstance } from "axios";
//封装的一个toast的文件 用到了element-plus(注意安装 配置,也可以用vant 用哪个组件库都行) 代码会放在下面
import { toast } from "@/common/utils/tips";
//基础地址文件代码会放在下面
import { getApiUrl } from "@/common/value/string";

class HttpRequest {
//axios的数据类型 AxiosInstance
  static axiosInstance: AxiosInstance;
  static init() {
    //创建axios实例
    this.axiosInstance = axios.create();
    // 设置请求超时
    this.axiosInstance.defaults.timeout = 100000;
    // 表示跨域请求时是否需要使用凭证
    // this.axiosInstance.defaults.withCredentials = true

    // 环境的切换,`baseURL` 将自动加在 `url` 前面,除非 `url` 是一个绝对 URL
    //不同的环境下的基础地址可能会不同,逻辑在基础地址文件中
    //process.env.NODE_ENV 所处的环境 是开发 测试之类的,获取不同的baseURL 
    this.axiosInstance.defaults.baseURL = getApiUrl(process.env.NODE_ENV);

    // 设置 post 请求头    application/x-www-form-urlencoded;application/json
    // this.axiosInstance.defaults.headers.common["Authorization"] =
    //   ticketStore.fullToken;(获取token之类的写在了index.ts文件里)
    this.axiosInstance.defaults.headers.post["Content-Type"] =
      "application/json;charset=UTF-8;";
  

    // 初始化拦截器
    this.initInterceptors();
    return this.axiosInstance;
  }

  static initInterceptors() {
    // 添加请求拦截器
    this.axiosInstance.interceptors.request.use(
      (config) => {
        // 在发送请求之前做些什么

        /* 登录流程控制中,根据本地是否存在 token 判断用户的登录情况
                但是即使 token 存在,也有可能 token 是过期的,所以在每次的请求头中携带 token
                后台根据携带的 token 判断用户的登录情况,并返回给我们对应的状态码
                而后我们可以在响应拦截器中,根据状态码进行一些统一的操作 */
        // webStorage.ls.get('token') && (config.headers.Authorization = `Bearer ${webStorage.ls.get('token')}`);
        return config;
      },
      (error) => {
        // 对请求错误做些什么
        return Promise.reject(error);
      }
    );
    // 添加响应拦截器
    this.axiosInstance.interceptors.response.use(
      (response) => {
        // 对响应数据做点什么
        // 如果返回的状态码为200,说明接口请求成功,可以正常拿到数据,否则的话抛出错误
        if (response.status === 200) {
            //这里.data,请求数据的时候就不用.data了
          return Promise.resolve(response.data);
        } else {
          return Promise.reject(response);
        }
        // return response;
      },
      (error) => {
        // 服务器状态码不是 200 的情况
        // 对响应错误做点什么

        const { config, code, request, response, isAxiosError, toJSON } = error;
        if (response) {
          // 请求已发出,但是不在2xx的范围 调用错误处理的方法(把状态码,错误的提示信息传进去)
          this.errorHandle(response.status, response.data.message);
          return Promise.reject(response);
        } else {
          // 超时提示
          if (error.message.includes("timeout")) {
            toast("请求超时,请稍后重试", "fail");
            return Promise.reject(error);
          }

          /* 处理断网的情况
                    eg: 请求超时或断网时,更新 state 的 network 状态
                    network 状态在 app.vue 中控制着一个全局的断网提示组件的显示隐藏
                    关于断网组件中的刷新重新获取数据,会在断网组件中说明 */
          if (!window.navigator.onLine) {
            // 如果断网....
            // store.commit('changeNetwork', false);
          } else {
            return Promise.reject(error);
          }
        }
      }
    );
  }

  /**
   * 请求失败后的错误统一处理
   * @param {Number} status 请求失败的状态码
   * 1**  信息,服务器收到请求,需要请求者继续执行操作
   * 2**  成功,操作被成功接收并处理
   * 3**  重定向,需要进一步的操作以完成请求
   * 4**  客户端错误,请求包含语法错误或无法完成请求
   * 5**  服务器错误,服务器在处理请求的过程中发生了错误
   */

  static errorHandle(status: number, other: string) {
    // 状态码判断
    switch (status) {
      // 400: 请求错误
      case 400:
        toast("请求错误", "fail");
        break;
      // 401: 未登录状态,跳转登录页
      case 401:
        toast("登陆状态已过期,请重新登录", "fail");

        // window.location.href = process.env.VUE_APP_YFTXGLPT
        break;
      // 403 权限不足,拒绝访问
      case 403:
        toast("权限不足,拒绝访问", "fail");
        break;
      // 404请求不存在
      case 404:
        toast("请求的资源不存在或请求地址出错", "fail");
        break;
      // 服务器错误
      case 500:
        toast("服务器错误", "fail");
        break;
      // token异常
      case 10001:
        toast("token异常,请联系管理员", "fail");
        break;
      default:
        console.log(other);
    }
  }
}

export default HttpRequest.init();

/**
 * 100  继续。客户端应继续其请求
 * 101  切换协议。服务器根据客户端的请求切换协议。只能切换到更高级的协议,例如,切换到HTTP的新版本协议
 *
 * 200  请求成功。一般用于GET与POST请求
 * 201  已创建。成功请求并创建了新的资源
 * 202  已接受。已经接受请求,但未处理完成
 * 203  非授权信息。请求成功。但返回的meta信息不在原始的服务器,而是一个副本
 * 204  无内容。服务器成功处理,但未返回内容。在未更新网页的情况下,可确保浏览器继续显示当前文档
 * 205  重置内容。服务器处理成功,用户终端(例如:浏览器)应重置文档视图。可通过此返回码清除浏览器的表单域
 * 206  部分内容。服务器成功处理了部分GET请求
 *
 * 300  多种选择。请求的资源可包括多个位置,相应可返回一个资源特征与地址的列表用于用户终端(例如:浏览器)选择
 * 301  永久移动。请求的资源已被永久的移动到新URI,返回信息会包括新的URI,浏览器会自动定向到新URI。今后任何新的请求都应使用新的URI代替
 * 302  临时移动。与301类似。但资源只是临时被移动。客户端应继续使用原有URI
 * 303  查看其它地址。与301类似。使用GET和POST请求查看
 * 304  未修改。所请求的资源未修改,服务器返回此状态码时,不会返回任何资源。客户端通常会缓存访问过的资源,通过提供一个头信息指出客户端希望只返回在指定日期之后修改的资源
 * 305  使用代理。所请求的资源必须通过代理访问
 * 306  已经被废弃的HTTP状态码
 * 307  临时重定向。与302类似。使用GET请求重定向
 *
 * 400  客户端请求的语法错误,服务器无法理解
 * 401  请求要求用户的身份认证
 * 402  保留,将来使用
 * 403  服务器理解请求客户端的请求,但是拒绝执行此请求
 * 404  服务器无法根据客户端的请求找到资源(网页)。通过此代码,网站设计人员可设置"您所请求的资源无法找到"的个性页面
 * 405  客户端请求中的方法被禁止
 * 406  服务器无法根据客户端请求的内容特性完成请求
 * 407  请求要求代理的身份认证,与401类似,但请求者应当使用代理进行授权
 * 408  服务器等待客户端发送的请求时间过长,超时
 * 409  服务器完成客户端的 PUT 请求时可能返回此代码,服务器处理请求时发生了冲突
 * 410  客户端请求的资源已经不存在。410不同于404,如果资源以前有现在被永久删除了可使用410代码,网站设计人员可通过301代码指定资源的新位置
 * 411  服务器无法处理客户端发送的不带Content-Length的请求信息
 * 412  客户端请求信息的先决条件错误
 * 413  由于请求的实体过大,服务器无法处理,因此拒绝请求。为防止客户端的连续请求,服务器可能会关闭连接。如果只是服务器暂时无法处理,则会包含一个Retry-After的响应信息
 * 414  请求的URI过长(URI通常为网址),服务器无法处理
 * 415  服务器无法处理请求附带的媒体格式
 * 416  客户端请求的范围无效
 * 417  服务器无法满足Expect的请求头信息
 *
 * 500  服务器内部错误,无法完成请求
 * 501  服务器不支持请求的功能,无法完成请求
 * 502  作为网关或者代理工作的服务器尝试执行请求时,从远程服务器接收到了一个无效的响应
 * 503  由于超载或系统维护,服务器暂时的无法处理客户端的请求。延时的长度可包含在服务器的Retry-After头信息中
 * 504  充当网关或代理的服务器,未及时从远端服务器获取请求
 * 505  服务器不支持请求的HTTP协议的版本,无法完成处理
 */

首先是 封装的toast 文件(作用就是提示信息)创建utils文件夹(tips.ts文件)//取什么名字都行

 

 ticps.ts 里面的完整代码(注意安装element-plus或者vant 下面有介绍)

import { ElNotification } from "element-plus";
import "element-plus/es/components/notification/style/css";

//封装全局toast
export const toast = (msg: string, type: string = "default") => {
  switch (type) {
    case "default":
      ElNotification({
        title: "提示",
        message: msg,
        type: "info",
      });
      break;
    case "success":
      ElNotification({
        title: "成功",
        message: msg,
        type: "success",
      });
      break;
    case "fail":
      ElNotification({
        title: "错误",
        message: msg,
        type: "error",
      });
      break;
    case "warning":
      ElNotification({
        title: "警告",
        message: msg,
        type: "warning",
      });
      return toast;
  }
};
export const getApiUrl = (nodeEvn: string | undefined): string => {
//判断传过来的环境类型 后面写不同的地址 我就随便写成一样的了 要按照环境写地址 不区分那么多的就写成一样的 (你的地址)
  switch (nodeEvn) {
    case "development":
      return "http://172.18.1.157:1010/";
    case "test":
      return "http://172.18.1.157:1010/";
    case "production":
      return "http://172.18.1.157:1010/";
    default:
      return "http://172.18.1.157:1010/";
  }
};

基础地址的代码:建一个文件夹(value---string.ts)(名字随便 注意修改axios.ts里面的引入路径就行)

安装 element-plus 因为用到了里面的一个小组件关于是完整引入还是按需引入 可以参考文档或者是另一篇文章(14条消息) vue3 Element-plus 的配置(按需引入,完整引入)_栀暖__的博客-优快云博客

封装get post 等接口

在index.ts里面(其中用到了一些从本地取数据)

import instance from '@/common/http/axios'


const ticketStore = useTicketStore()

interface responseInter {
    success: boolean
    info: string
    result: any
    code: string
}

const request = async ({
    method,
    url,
    data,
    config,
    loading = false,
//接口地址上有没有api
    withoutApiString = false,
}: any): Promise<responseInter> => {
    method = method.toLowerCase()

    //实时获取新的token
    instance.defaults.headers['Authorization'] = 从本地获取到的完整的token

    if (withoutApiString === false) url = 'api' + url
    if (method == 'post') {
        return instance.post(url, data, { ...config },)
    } else if (method == 'get') {
        return instance.get(url, {
            params: data,
            ...config
        })
    } else if (method == 'delete') {
        return instance.delete(url, {
            params: data,
            ...config
        })
    } else if (method == 'put') {
        return instance.put(url, data, { ...config })
    } else {
        console.error('未知的method' + method)
        return {
            success: false,
            info: '未知method',
            result: {},
            code: 'fail',
        }
    }
}

export {
    request,
    type responseInter,
}

使用封装好的request之后,看接口地址有没有api 默认是false,没有的话就加withoutApiString:true

然后就封装好了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值