M-AdminM-Admin
首页
指南
  • MTable
  • MForm
  • MTinymce
  • 季度选择器
  • MSearchForm
  • 预览地址
  • Gitee源码
  • Github源码
  • 更新日志
捐赠
首页
指南
  • MTable
  • MForm
  • MTinymce
  • 季度选择器
  • MSearchForm
  • 预览地址
  • Gitee源码
  • Github源码
  • 更新日志
捐赠
  • 指南

    • 介绍
    • 快速上手
    • 目录结构
    • 路由、菜单
    • 权限管理
    • 系统配置
  • 进阶

    • 网络请求
    • 国际化配置
    • Hooks
    • Store
    • TSX 支持
  • 组件教程

    • MTable
    • MForm
    • MTinymce
    • 季度选择器
    • MSearchForm
  • 其他

    • 项目代码规范
    • 常见问题

网络请求

  • 项目封装了 Axios 来做网络请求,包括请求错误处理、请求重试等功能。
  • 可以根据实际使用需求进行封装。

目录结构


request
├─ axios-cancel.ts                  ## axios 取消请求封装
├─ axios-service.ts                 ## axios 请求service
├─ axios-transform.ts               ## axios 抽象类
├─ index.ts                         ## 请求配置
├─ type.d.ts
└─ utils.ts                         ## utils

配置


function createAxios(opt?: Partial<CreateAxiosOptions>) {
  return new VAxios(
    merge(
      <CreateAxiosOptions>{
        // 请求头,根据实际需求来确定是否需要请求头
        authenticationScheme: "saToken",
        {/* // authenticationScheme: '', */}
        // 超时 时间,默认为10s
        timeout: ResultEnum.TIMEOUT as number,
        // 携带Cookie
        withCredentials: false,
        // 头信息
        headers: { 'Content-Type': ContentTypeEnum.JSON },
        // 数据处理方式
        transform,
        // 配置项,下面的选项都可以在独立的接口请求中覆盖
        requestOptions: {
          // 接口地址
          apiUrl: import.meta.env.VITE_API_BASE_URL,
          // 是否自动添加接口前缀
          isJoinPrefix: true,
          // 接口前缀
          urlPrefix: '/api',
          // 是否返回原生响应头 比如:需要获取响应头时使用该属性
          isReturnNativeResponse: false,
          // 需要对返回数据进行处理
          isTransformResponse: true,
          // post请求的时候添加参数到url
          joinParamsToUrl: false,
          // 格式化提交参数时间
          formatDate: true,
          // 是否加入时间戳
          joinTime: true,
          // 忽略重复请求
          ignoreRepeatRequest: true,
          // 是否携带token
          withToken: true,
          // 重试
          retry: {
            count: 3,
            delay: 2000,
          },
        },
      },
      opt || {}
    )
  )
}

提示:

apiUrl是通过环境变量加载的,可以通过项目根目录下的.env.***文件中修改VITE_API_BASE_URL,而不是在此处直接修改

请求拦截

请求拦截:可以在此处对请求头进行设置等操作。 代码位置:index.ts 110 行

 // 请求拦截器处理,设置请求头
    requestInterceptors: (config: any, options: any ) => {
    // 请求之前处理config
    if (config.url?.indexOf('/user/login') > -1) {
      console.log('不需要进行请求头设置')
    } else {
      const token = getToken()
      if (token && (config as Recordable)?.requestOptions?.withToken !== false) {
        ;(config as Recordable).headers['token'] = `${token}`
      }
    }

    return config as InternalAxiosRequestConfig
  },

相应拦截

 // 响应拦截器处理,根据返回的code再进行处理,用来处理业务异常
  responseInterceptors: (res: any) => {
    if (res?.status !== ResultEnum.SUCCESS) {
      Message.error('网络错误!')
    }
    // 请求成功
    else if (res?.data.code === ResultEnum.SUCCESS && res?.status === ResultEnum.SUCCESS) {
      return res
    }
    // 请求文件成功
    else if (String(res?.data.code) === 'undefined' && typeof res?.data && res?.status === ResultEnum.SUCCESS) {
      return res
    }
    // 请求报错
    else {
      Message.error(res?.data.message)
      setTimeout(() => {
        if (router) router.push('/login')
        else window.location.href = '/login'
      }, 1000)
    }
  },

  // 响应错误处理,根据后端返回错误码进行响应,TODO
  responseInterceptorsCatch: (error: any) => {
    const { config, response } = error
    if (!config || !config.requestOptions.retry) {
      Message.error({ content: response?.message, duration: 1000 })
      return Promise.reject(error)
    }
    // 接口请求重试
    config.retryCount = config.retryCount || 1

    if (config.retryCount >= config.requestOptions.retry.count) return Promise.reject(error)

    config.retryCount += 1

    const backoff = new Promise((resolve) => {
      setTimeout(() => {
        resolve(config)
      }, config.requestOptions.retry.delay || 1)
    })
    config.headers = { ...config.headers, 'Content-Type': ContentTypeEnum.JSON }
    return backoff.then((config) => request.request(config))
  },

  • 在获取接口相应后,如果失败会进行重试操作,重试次数自行配置。
  • 请求成功后,会根据返回的 code 做处理,具体根据项目需求进行配置。

示例

  • 1.在 src/api 下创建文件 login.ts
  • 2.在 login.ts 中引入封装后的 request
  • 3.编写请求函数
import { request } from '@/utils/request'
import { Result } from '@/utils/request/type'
import { LoginData } from './types'

/**
 * @name 登录模块
 * */

const Api = {
  login: '/user/login', // 登录
  logout: '/user/logout', // 登出
}

/**
 * @description login
 * @param data
 * */
export const login = (data: {account:string,password:string}) => {
  return request.post<Result>({
    url: `${Api.login}`,
    data
  })
}

/**
 * @description logout
 * */
export const logout = () => {
  return request.get<Result>({
    url: Api.logout,
  })
}

axios 封装调用

import { login } from "@/api/login";

const formData =
  reactive <
  { account: string, password } >
  {
    account: "admin",
    password: "admin",
  };

const handleSubmit = async () => {
  const response = await login(formData);
  // 进行其他处理......
};

最近更新:: 2025/6/20 05:46
Contributors: xuyp
Next
国际化配置