/src/utils/request.ts:axios 请求封装,适用于需要统一处理请求和响应的场景

文章目录

json 复制代码
console.log('Intercepted Response:', JSON.stringify(response));
json 复制代码
{
  "data": {
    "code": 0,
    "msg": "成功",
    "data": {
      "id": 76,
      "inviteCode": "957989",
      "invitorId": 56,
      "remark": "测试",
      "generatedDate": "2025-01-08T16:55:27.163",
      "expireTime": "2025-01-15T16:55:27.163",
      "inviteLevel": 2,
      "status": 0,
      "boundPhone": null,
      "weixinNickname": null,
      "weixinHeadimg": null,
      "boundWxUid": null,
      "adminId": null,
      "userId": null,
      "isLocked": 0,
      "createdDate": "2025-01-08T16:55:27.163",
      "lastModifiedDate": "2025-01-08T16:55:27.163"
    }
  },
  "status": 200,
  "statusText": "",
  "headers": {
    "cache-control": "no-cache, no-store, max-age=0, must-revalidate",
    "content-type": "application/json;charset=UTF-8",
    "expires": "0",
    "pragma": "no-cache"
  },
  "config": {
    "url": "/api/invite-codes/generate",
    "method": "post",
    "params": {
      "invitorId": 56,
      "remark": "测试"
    },
    "headers": {
      "Accept": "application/json, text/plain, */*",
      "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhdWQiOiI1NiIsInJvbGUiOiJST0xFX0NPTVBBTllfU1VQRVIiLCJleHAiOjE3MzY0MDA5MDMsInVzZXJOYW1lIjoiMTg2NjE5Nzc1ODEiLCJ0eXBlIjoiYWRtaW4iLCJpYXQiOjE3MzYzMTQ1MDN9.OBFnxtoE4A2RO6gAcVm_CUkvJl_j6wpUkOPZOZySwEk"
    },
    "baseURL": "http://127.0.0.1:8087/",
    "transformRequest": [null],
    "transformResponse": [null],
    "timeout": 0,
    "withCredentials": false,
    "xsrfCookieName": "XSRF-TOKEN",
    "xsrfHeaderName": "X-XSRF-TOKEN",
    "maxContentLength": -1
  },
  "request": {}
}

数据结构解释

  • data : 包含实际业务响应数据,其中:
    • code: 响应码,0 表示成功。
    • msg: 响应消息。
    • data: 具体数据,包括邀请码的详细信息。
  • status : HTTP 状态码,200 表示请求成功。
  • headers: 响应头信息。
  • config: 请求配置详情,包括 URL、请求方法、参数、头部信息等。
  • request: 请求对象,具体内容在此为空。

如需对其中的字段进行详细解析,请告知我! 😊

ts 复制代码
// spid-admin/src/utils/request.ts
import axios from 'axios'
import { Message, MessageBox } from 'element-ui'
import { UserModule } from '@/store/modules/user'
import { api } from '@/utils/public-path'

let logoutCount:number = 0
const service = axios.create({
  baseURL: api, // url = base url + request url
  timeout: 0,
  withCredentials: false // send cookies when cross-domain requests
})

// Request interceptors
service.interceptors.request.use(
  (config) => {
    // Add X-Access-Token header to every request, you can add other custom headers here
    if (UserModule.token) {
      const { token }: any = JSON.parse(UserModule.token)
      config.headers['token'] = token
    }
    //console.log('Request config:', config); // 添加这行代码
    return config
  },
  (error) => {
    Promise.reject(error)
  }
)

// Response interceptors
service.interceptors.response.use(
  (response) => {
    //console.log('Intercepted Response:', JSON.stringify(response));
    //console.log('Full Response Data:', JSON.stringify(response, null, 2));
    // Some example codes here:
    // You can change this part for your own usage.
    // status == 200: success
    // code === 0: success
    // code === 1: invalid access token

    const res = response.data
    if (res.code !== 0) {
      if (res.code === 1) {
        Message({
          message: res.msg || 'Error',
          type: 'warning',
          duration: 5 * 1000
        })
        return response.data
      } else if (res.code === 7) {
        MessageBox.confirm(
          '你已被登出,可以取消继续留在该页面,或者重新登录',
          '确定登出',
          {
            confirmButtonText: '重新登录',
            cancelButtonText: '取消',
            type: 'warning'
          }
        ).then(() => {
          logoutCount = 0
          localStorage.clear()
          sessionStorage.clear()
          UserModule.ResetToken()
          location.reload() // To prevent bugs from vue-router
        })
      } else if (res.indexOf('form') !== -1) {
        // 支付宝支付 ....... 为什么不改造成正常接口呢 不理解
        return Promise.resolve(res)
      } else {
        Message({
          message: res.msg || 'Error',
          type: 'error',
          duration: 5 * 1000
        })
        return Promise.reject(new Error(res.msg || 'Error'))
      }
    } else {
      return response.data
    }
  },
  (error) => {
    console.log(error)
    let errorInfo = error.response
    let msg
    if (!errorInfo) {
      const { request: { statusText, status }, config } = JSON.parse(JSON.stringify(error))
      errorInfo = {
        statusText,
        status,
        request: { responseURL: config.url }
      }
      msg = status + ':' + errorInfo.statusText
    } else {
      if (error.response.data.code === -1) {
        if (logoutCount === 0) {
          MessageBox.confirm(
            '你已被登出,可以取消继续留在该页面,或者重新登录',
            '确定登出',
            {
              confirmButtonText: '重新登录',
              cancelButtonText: '取消',
              type: 'warning'
            }
          ).then(() => {
            logoutCount = 0
            localStorage.clear()
            sessionStorage.clear()
            UserModule.ResetToken()
            location.reload() // To prevent bugs from vue-router
            msg = error.response.data.msg
          })
          logoutCount++
          return
        }
      } else if (errorInfo.data.code === 1 || errorInfo.data.code === 2) {
        msg = errorInfo.data.msg
      } else {
        msg = error.response.data.status + ':' + error.response.data.message
      }
    }
    Message({
      message: msg,
      type: 'error',
      duration: 5 * 1000
    })
    return Promise.reject(msg)
  }
)

export default service

这段代码是一个基于 axios 的请求封装,主要用于处理 HTTP 请求的拦截和响应拦截。它结合了 Element UI 的消息提示和弹窗组件,实现了以下功能:


1. 核心功能

  • 请求拦截
    • 在请求发送之前,检查用户是否已登录(通过 UserModule.token)。
    • 如果用户已登录,将 token 添加到请求头中。
  • 响应拦截
    • 对响应数据进行统一处理,根据返回的 code 值判断请求是否成功。
    • 处理特定的错误码(如 code === 1code === 7),并显示相应的提示信息。
    • 在用户登录状态失效时,弹出确认框提示用户重新登录。

2. 代码结构分析

请求拦截器
typescript 复制代码
service.interceptors.request.use(
  (config) => {
    if (UserModule.token) {
      const { token }: any = JSON.parse(UserModule.token);
      config.headers['token'] = token;
    }
    return config;
  },
  (error) => {
    Promise.reject(error);
  }
);
  • 功能
    • 在每次请求发送之前,检查用户是否已登录。
    • 如果已登录,将 token 添加到请求头中。
  • 注意
    • UserModule.token 是从 Vuex 模块中获取的,需要确保 UserModule 已正确初始化。

响应拦截器
typescript 复制代码
service.interceptors.response.use(
  (response) => {
    const res = response.data;
    if (res.code !== 0) {
      if (res.code === 1) {
        Message({
          message: res.msg || 'Error',
          type: 'warning',
          duration: 5 * 1000,
        });
        return response.data;
      } else if (res.code === 7) {
        MessageBox.confirm(
          '你已被登出,可以取消继续留在该页面,或者重新登录',
          '确定登出',
          {
            confirmButtonText: '重新登录',
            cancelButtonText: '取消',
            type: 'warning',
          }
        ).then(() => {
          logoutCount = 0;
          localStorage.clear();
          sessionStorage.clear();
          UserModule.ResetToken();
          location.reload(); // To prevent bugs from vue-router
        });
      } else if (res.indexOf('form') !== -1) {
        // 支付宝支付 ....... 为什么不改造成正常接口呢 不理解
        return Promise.resolve(res);
      } else {
        Message({
          message: res.msg || 'Error',
          type: 'error',
          duration: 5 * 1000,
        });
        return Promise.reject(new Error(res.msg || 'Error'));
      }
    } else {
      return response.data;
    }
  },
  (error) => {
    console.log(error);
    let errorInfo = error.response;
    let msg;
    if (!errorInfo) {
      const { request: { statusText, status }, config } = JSON.parse(JSON.stringify(error));
      errorInfo = {
        statusText,
        status,
        request: { responseURL: config.url },
      };
      msg = status + ':' + errorInfo.statusText;
    } else {
      if (error.response.data.code === -1) {
        if (logoutCount === 0) {
          MessageBox.confirm(
            '你已被登出,可以取消继续留在该页面,或者重新登录',
            '确定登出',
            {
              confirmButtonText: '重新登录',
              cancelButtonText: '取消',
              type: 'warning',
            }
          ).then(() => {
            logoutCount = 0;
            localStorage.clear();
            sessionStorage.clear();
            UserModule.ResetToken();
            location.reload(); // To prevent bugs from vue-router
            msg = error.response.data.msg;
          });
          logoutCount++;
          return;
        }
      } else if (errorInfo.data.code === 1 || errorInfo.data.code === 2) {
        msg = errorInfo.data.msg;
      } else {
        msg = error.response.data.status + ':' + error.response.data.message;
      }
    }
    Message({
      message: msg,
      type: 'error',
      duration: 5 * 1000,
    });
    return Promise.reject(msg);
  }
);
  • 功能
    • 对响应数据进行统一处理。
    • 根据返回的 code 值判断请求是否成功,并显示相应的提示信息。
    • 处理特定的错误码(如 code === 1code === 7),并在用户登录状态失效时弹出确认框提示用户重新登录。
  • 注意
    • code === 7 表示用户登录状态失效,会清除本地存储并刷新页面。
    • code === 1 表示请求失败,会显示警告信息。
    • 其他错误码会显示错误信息。

3. 改进建议

  • 支付宝支付逻辑
    • 代码中提到 res.indexOf('form') !== -1 是处理支付宝支付的逻辑,但注释中提到"为什么不改造成正常接口呢 不理解"。建议将支付宝支付逻辑改造为标准的接口返回格式,以便统一处理。
  • 错误处理
    • error.response 为空时,手动构造错误信息。可以考虑使用更健壮的方式处理网络错误。
  • logoutCount 的作用
    • logoutCount 用于防止多次弹出登录失效的确认框。可以考虑使用更优雅的方式实现,例如在 Vuex 中维护登录状态。

4. 总结

这段代码是一个典型的 axios 请求封装,适用于需要统一处理请求和响应的场景。它结合了 Element UI 的消息提示和弹窗组件,提供了良好的用户体验。通过进一步优化错误处理和逻辑封装,可以提高代码的可维护性和健壮性。

相关推荐
Excel_VBA表格จุ๊บ2 小时前
wps宏js接入AI功能和接入翻译功能
javascript·wps·js宏
hikktn2 小时前
Java 兼容读取WPS和Office图片,结合EasyExcel读取单元格信息
java·开发语言·wps
小青柑-3 小时前
Go语言中的接收器(Receiver)详解
开发语言·后端·golang
豪宇刘3 小时前
JavaScript 延迟加载的方法
开发语言·javascript
摇光934 小时前
js迭代器模式
开发语言·javascript·迭代器模式
美丽的欣情4 小时前
Qt实现海康OSD拖动Demo
开发语言·qt
C++小厨神5 小时前
Bash语言的计算机基础
开发语言·后端·golang
BinaryBardC5 小时前
Bash语言的软件工程
开发语言·后端·golang
飞yu流星5 小时前
C++ 函数 模板
开发语言·c++·算法
没有名字的鬼5 小时前
C_字符数组存储汉字字符串及其索引
c语言·开发语言·数据结构