拿来即用,自己封装的 axios

news/2024/6/17 2:57:03 标签: 前端, javascript, java

文章目录

    • 一、需求
    • 二、分析
      • 1. 安装axios
      • 2. 新建一个 ts 文件,封装 axios
      • 3. store 存放 token 信息
      • 4. 使用
      • 5. 文件 type.js

一、需求

在日常开发中,我们会经常用到 axios ,那么如何在自己的项目中自己封装 axios

二、分析

1. 安装axios

npm install axios

2. 新建一个 ts 文件,封装 axios

手写一个TS文件: src\utils\request.ts,我的习惯把它放在 utils 目录下,源码如下

import axios, { InternalAxiosRequestConfig, AxiosResponse } from "axios";
import { useUserStoreHook } from "@/store/modules/user";

// 创建 axios 实例
const service = axios.create({
  baseURL: import.meta.env.VITE_APP_BASE_API,
  timeout: 50000,
  headers: { "Content-Type": "application/json;charset=utf-8" },
});

// 请求拦截器
service.interceptors.request.use(
  (config: InternalAxiosRequestConfig) => {
    const userStore = useUserStoreHook();
    if (userStore.token) {
      config.headers.Authorization = userStore.token;
    }
    return config;
  },
  (error: any) => {
    return Promise.reject(error);
  }
);

// 响应拦截器
service.interceptors.response.use(
  (response: AxiosResponse) => {
    const { code, msg } = response.data;
    if (code === "00000") {
      return response.data;
    }
    // 响应数据为二进制流处理(Excel导出)
    if (response.data instanceof ArrayBuffer) {
      return response;
    }

    ElMessage.error(msg || "系统出错");
    return Promise.reject(new Error(msg || "Error"));
  },
  (error: any) => {
    if (error.response.data) {
      const { code, msg } = error.response.data;
      // token 过期,重新登录
      if (code === "A0230") {
        ElMessageBox.confirm("当前页面已失效,请重新登录", "提示", {
          confirmButtonText: "确定",
          type: "warning",
        }).then(() => {
          localStorage.clear();
          window.location.href = "/";
        });
      } else {
        ElMessage.error(msg || "系统出错");
      }
    }
    return Promise.reject(error.message);
  }
);

// 导出 axios 实例
export default service;

3. store 存放 token 信息

我的 store 中存放了用户的登录信息,在封装 axios 时只用到了 token,因此下方代码可做参考

import { defineStore } from "pinia";

import { loginApi, logoutApi } from "@/api/auth";
import { getUserInfo } from "@/api/user";
import { resetRouter } from "@/router";
import { store } from "@/store";

import { LoginData } from "@/api/auth/types";
import { UserInfo } from "@/api/user/types";

import { useStorage } from "@vueuse/core";

export const useUserStore = defineStore("user", () => {
  // state
  const userId = ref();
  const token = useStorage("accessToken", "");
  const nickname = ref("");
  const avatar = ref("");
  const roles = ref<Array<string>>([]); // 用户角色编码集合 → 判断路由权限
  const perms = ref<Array<string>>([]); // 用户权限编码集合 → 判断按钮权限

  /**
   * 登录调用
   *
   * @param {LoginData}
   * @returns
   */
  function login(loginData: LoginData) {
    return new Promise<void>((resolve, reject) => {
      loginApi(loginData)
        .then((response) => {
          const { tokenType, accessToken } = response.data;
          token.value = tokenType + " " + accessToken; // Bearer eyJhbGciOiJIUzI1NiJ9.xxx.xxx
          resolve();
        })
        .catch((error) => {
          reject(error);
        });
    });
  }

  // 获取信息(用户昵称、头像、角色集合、权限集合)
  function getInfo() {
    return new Promise<UserInfo>((resolve, reject) => {
      getUserInfo()
        .then(({ data }) => {
          if (!data) {
            return reject("Verification failed, please Login again.");
          }
          if (!data.roles || data.roles.length <= 0) {
            reject("getUserInfo: roles must be a non-null array!");
          }
          userId.value = data.userId;
          nickname.value = data.nickname;
          avatar.value = data.avatar;
          roles.value = data.roles;
          perms.value = data.perms;
          resolve(data);
        })
        .catch((error) => {
          reject(error);
        });
    });
  }

  // 注销
  function logout() {
    return new Promise<void>((resolve, reject) => {
      logoutApi()
        .then(() => {
          resetRouter();
          resetToken();
          location.reload(); // 清空路由
          resolve();
        })
        .catch((error) => {
          reject(error);
        });
    });
  }

  // 重置
  function resetToken() {
    token.value = "";
    nickname.value = "";
    avatar.value = "";
    roles.value = [];
    perms.value = [];
  }
  return {
    token,
    nickname,
    avatar,
    roles,
    perms,
    login,
    getInfo,
    logout,
    resetToken,
    /**
     * 当前登录用户ID
     */
    userId,
  };
});

// 非setup
export function useUserStoreHook() {
  return useUserStore(store);
}

4. 使用

import request from "@/utils/request";
import { AxiosPromise } from "axios";
import { UserForm, UserInfo, UserQuery } from "./types";

/**
 * 登录成功后获取用户信息(昵称、头像、权限集合和角色集合)
 */
export function getUserInfo(): AxiosPromise<UserInfo> {
  return request({
    url: "/api/v1/users/me",
    method: "get",
  });
}

/**
 * 添加用户
 *
 * @param data
 */
export function addUser(data: any) {
  return request({
    url: "/api/v1/users",
    method: "post",
    data: data,
  });
}
/**
 * 修改用户
 *
 * @param id
 * @param data
 */
export function updateUser(id: number, data: UserForm) {
  return request({
    url: "/api/v1/users/" + id,
    method: "put",
    data: data,
  });
}
/**
 * 修改用户状态
 *
 * @param id
 * @param status
 */
export function updateUserStatus(id: number, status: number) {
  return request({
    url: "/api/v1/users/" + id + "/status",
    method: "patch",
    params: { status: status },
  });
}
/**
 * 删除用户
 *
 * @param ids
 */
export function deleteUsers(ids: string) {
  return request({
    url: "/api/v1/users/" + ids,
    method: "delete",
  });
}
/**
 * 下载用户导入模板
 *
 * @returns
 */
export function downloadTemplateApi() {
  return request({
    url: "/api/v1/users/template",
    method: "get",
    responseType: "arraybuffer",
  });
}

/**
 * 导出用户
 *
 * @param queryParams
 * @returns
 */
export function exportUser(queryParams: UserQuery) {
  return request({
    url: "/api/v1/users/_export",
    method: "get",
    params: queryParams,
    responseType: "arraybuffer",
  });
}

/**
 * 导入用户
 *
 * @param file
 */
export function importUser(deptId: number, file: File) {
  const formData = new FormData();
  formData.append("file", file);
  return request({
    url: "/api/v1/users/_import",
    method: "post",
    params: { deptId: deptId },
    data: formData,
    headers: {
      "Content-Type": "multipart/form-data",
    },
  });
}

5. 文件 type.js

/**
 * 用户查询对象类型
 */
export interface UserQuery {
  keywords?: string;
  status?: number;
  deptId?: number;
}

/**
 * 登录用户信息
 */
export interface UserInfo {
  userId: number;
  nickname: string;
  avatar: string;
  roles: string[];
  perms: string[];
}

/**
 * 用户表单类型
 */
export interface UserForm {
  /**
   * 用户头像
   */
  avatar?: string;
  /**
   * 部门ID
   */
  deptId?: number;
  /**
   * 邮箱
   */
  email?: string;
  /**
   * 性别
   */
  gender?: number;
  /**
   * 用户ID
   */
  id?: number;
  mobile?: string;
  /**
   * 昵称
   */
  nickname?: string;
  /**
   * 角色ID集合
   */
  roleIds?: number[];
  /**
   * 用户状态(1:正常;0:禁用)
   */
  status?: number;
  /**
   * 用户名
   */
  username?: string;
}


http://www.niftyadmin.cn/n/4943850.html

相关文章

【STM32RT-Thread零基础入门】 4. 线程介绍(理论)

文章目录 前言一、线程的概念二、线程的调度三、上下文切换四、线程的重要属性1. 线程栈2. 线程的状态3. 线程优先级4. 线程时间片5. 线程的入口函数 五、RT-Thread命令查看系统线程信息总结 前言 前文中的最后一个任务发现&#xff0c;一个main()函数很难同时实现按键功能和闪…

每天一道leetcode:1926. 迷宫中离入口最近的出口(图论中等广度优先遍历)

今日份题目&#xff1a; 给你一个 m x n 的迷宫矩阵 maze &#xff08;下标从 0 开始&#xff09;&#xff0c;矩阵中有空格子&#xff08;用 . 表示&#xff09;和墙&#xff08;用 表示&#xff09;。同时给你迷宫的入口 entrance &#xff0c;用 entrance [entrancerow, …

VScode替换cmd powershell为git bash 终端,并设置为默认

效果图 步骤 1. 解决VScode缺少git bash的问题_failed to start bash - is git-bash.exe on the syst_Rudon滨海渔村的博客-CSDN博客效果解决步骤找到git安装目录下的/bin/bash.exe&#xff0c;复制其绝对路径&#xff0c;例如D:\Program Files\Git\bin\bash.exe把路径的右斜…

探索高级UI、源码解析与性能优化,了解开源框架及Flutter,助力Java和Kotlin筑基,揭秘NDK的魅力!

课程链接&#xff1a; 链接: https://pan.baidu.com/s/13cR0Ip6lzgFoz0rcmgYGZA?pwdy7hp 提取码: y7hp 复制这段内容后打开百度网盘手机App&#xff0c;操作更方便哦 --来自百度网盘超级会员v4的分享 课程介绍&#xff1a; &#x1f4da;【01】Java筑基&#xff1a;全方位指…

Arduino MQTT客户端库PubSubClient快速入门

文章目录 目的基础说明示例代码总结 目的 MQTT是比较常用在物联网设备中的通讯协议&#xff0c;这篇文章将使用 Arudino ESP32 作为MQTT客户端进行通讯使用演示。目前Arduino的MQTT客户端库中最常使用的是 PubSubClient &#xff0c;所以本文也将以此进行说明。 主页&#xf…

FPGA: RS译码仿真过程

FPGA: RS译码仿真过程 在上一篇中记录了在FPGA中利用RS编码IP核完成信道编码的仿真过程&#xff0c;这篇记录利用译码IP核进行RS解码的仿真过程&#xff0c;带有程序和结果。 1. 开始准备 在进行解码的过程时&#xff0c;同时利用上一篇中的MATLAB仿真程序和编码过程&#x…

【Git】(二)分支

1、创建分支 已存在主分支master&#xff0c;现在需要创建v1.0的版本&#xff0c;一般直接在web页面操作。 v1.0分支&#xff0c;基线master&#xff0c;称为项目分支。 假如&#xff0c;v1.0项目存在两个项目成员sunriver2000和snow&#xff0c;一般还会再针对个人创建个人…

真·VB.NET彻底释放Interop.Excel对象

使用 Microsoft.Office.Interop.Excel 虽然有速度慢的缺点&#xff1b;但是作为自带引用&#xff0c;兼容性最好&#xff0c;而且是COM对象模型也很熟悉(Excel里直接录个宏&#xff0c;很方便把VBA代码转成VB.NET)。所以处理几百上千条的小数据时还是很方便的。 而 Microsoft.…