前端 vue axios封装+debug+error (包含文件上传加参) - 戴向天

大家好!我叫戴向天

QQ群:602504799

QQ:809002582

废话不多说,直接上代码↓↓↓

祝你前端开发愉快

import axios from 'axios' // 导入axios cmd安装  =>  淘宝镜像 ? cnpm install axios -S : npm install axios -S
import { backendPath, port, openDebug, ProjectName } from './base.js'

const maxRequest = 1 // 限制当前请求的错误次数
axios.defaults.headers.common['token'] = localStorage.getItem('token')

const headersConfig = () => { // 请求头配置
  return {
    // 这里就是配置一些请求的参数值
    'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8',
    'Access-Control-Allow-Origin': '*'
  }
}

const debugOrder = [] // 请求后台的记录

const debug = (params) => { // 请求后台的记录进行存储
  if (!openDebug) return false // 是否开始了记录存储
  // 如果有参数 就进行存储
  if (params) {
    debugOrder.push({
      ...params, // 请求的信息 以及回馈值
      headers: { // 请求头的信息
        ...headersConfig()
      },
      time: new Date().getTime() // 请求的时间
    })
  }
  return debugOrder // 返回所有的请求记录
}

axios.defaults.baseURL = '/' + ProjectName

axios.interceptors.response.use(function (response) {
  // 在接收响应做些什么,例如跳转到登录页
  if (typeof response.data === 'string') {
    const res = JSON.parse(response.data.replace(/'/g, '"'))
    response.data = res
  }
  return response
}, function (error) {
  // 对响应错误做点什么
  return Promise.reject(error)
})

/**
 GET请求
 */

async function requestByGet (url, params, num = 0) {
  if (!url) {
    return {
      code: 0,
      msg: 'haven\'t request url'
    }
  }
  let isRequestError = false // 是否请求失败
  let errorMsg = '' // 请求的错误信息

  let urlParams = '?'

  for (let i in params) {
    urlParams += `${i}=${params[i]}&`
  }
  urlParams = urlParams.substring(0, urlParams.length - 1)
  const result = await axios.get(`${backendPath + port}/${ProjectName}${url}${urlParams}`, {}, {
    headers: {
      ...headersConfig()
    }
  }).catch(error => {
    /** 当请求出现错误,就会执行 */
    isRequestError = !isRequestError
    errorMsg = error
  })

  if (isRequestError) { // 判断是否出现错误的请求
    // 判断错误次数是否在允许的范围内
    if (num < maxRequest) {
      const res = await requestByGet(url, params, num + 1)
      return res
    } else { // 超出了错误次数的范围内 将错误的信息进行返回出去
      return {
        code: 0,
        msg: errorMsg
      }
    }
  }

  debug({
    method: 'GET',
    url: `${backendPath}/${url}`,
    params,
    result
  })
  // console.log('get', result)
  return result // 返回最终的结果
}

/**
 POST请求
 */
async function requestByPost (url, params, num = 0) {
  if (!url) {
    return {
      code: 0,
      msg: 'haven\'t request url'
    }
  }

  let isRequestError = false // 是否请求失败
  let errorMsg = '' // 请求的错误信息

  // console.log('params', params)

  const urlParams = new URLSearchParams()

  for (let i in params) urlParams.append(i, params[i])

  const result = await axios({
    method: 'post',
    url: `${backendPath + port}/${ProjectName}${url}`,
    data: params
  }).catch(error => {
    /** 当请求出现错误,就会执行 */
    isRequestError = !isRequestError
    errorMsg = error
  })

  if (isRequestError) { // 判断是否出现错误的请求
    // 判断错误次数是否在允许的范围内
    if (num < maxRequest) {
      const res = await requestByPost(url, params, num + 1)
      return res
    } else { // 超出了错误次数的范围内 将错误的信息进行返回出去
      return {
        code: 0,
        msg: errorMsg
      }
    }
  }

  debug({
    method: 'POST',
    url: `${backendPath}/${url}`,
    params,
    result
  })

  return result // 返回最终的结果
}

async function requestUploadFiles (url, params, num = 0) {
  if (!url) {
    return {
      code: 0,
      msg: 'haven\'t request url'
    }
  }
  let isRequestError = false // 是否请求失败
  let errorMsg = '' // 请求的错误信息

  let formData = new FormData() // 创建form对象

  for (let i in params) {
    if (i === 'fils') {
      formData.append(i, params[i], params.file.name)
    } else {
      formData.append(i, params[i])
    }
  }
  const result = await axios.post(`${backendPath + port}/${ProjectName}${url}`, formData, {
    headers: {
      // ...headersConfig()
    }
  }
  ).catch(error => {
    /** 当请求出现错误,就会执行 */
    isRequestError = !isRequestError
    errorMsg = error
  })
  // console.log('requestUploadFiles = >result====>', result)
  if (isRequestError) { // 判断是否出现错误的请求
    // 判断错误次数是否在允许的范围内
    if (num < maxRequest) {
      const res = await requestUploadFiles(url, params, num + 1)
      return res
    } else { // 超出了错误次数的范围内 将错误的信息进行返回出去
      return {
        code: 0,
        msg: errorMsg
      }
    }
  }

  debug({
    method: 'POST',
    url: `${backendPath}/${url}`,
    params,
    result
  })

  return result
}

/** 最重要的一步 将方法导出 */
export {
  requestByGet, requestByPost, requestUploadFiles
}


### Vue 3 中封装 Axios 并配置代理 #### 封装 Axios 实例 为了更好地管理和维护 HTTP 请求,通常会创建一个独立的模块用于初始化和配置 Axios 实例。下面是一个简单的 `axios.js` 文件实现: ```javascript // src/utils/axios.js import axios from 'axios'; const service = axios.create({ baseURL: process.env.VUE_APP_BASE_API, // API 的 base_url timeout: 5000 // 请求超时时间 }); // 请求拦截器 service.interceptors.request.use( config => { // 在发送请求之前做些什么 return config; }, error => { // 对请求错误做些什么 return Promise.reject(error); } ); // 响应拦截器 service.interceptors.response.use( response => { const res = response.data; // 如果返回的状态码不是2xx,则认为是有错的 if (res.code !== 200) { Message({ message: res.message || 'Error', type: 'error' }); return Promise.reject(new Error(res.message || 'Error')); } else { return res; } }, error => { console.log('err' + error); // for debug Message({ message: error.message, type: 'error' }); return Promise.reject(error); } ); export default service; ``` 此部分代码展示了如何设置基础 URL 和默认超时,并定义了两个重要的中间件——请求前处理逻辑与响应后的数据解析[^2]。 #### 注册全局 `$http` 方法 为了让整个应用都能方便地访问这个自定义的 Axios 客户端实例,可以在应用程序启动时将其注册为全局属性。这可以通过修改项目的入口文件完成,如下所示: ```typescript // main.ts import { createApp } from 'vue'; import App from './App.vue'; import store from './store'; import router from './router'; import Vant from 'vant'; import 'vant/lib/index.css'; import axios from './utils/axios'; const app = createApp(App); app.config.globalProperties.$http = axios; app.use(store) .use(router) .use(Vant) .mount('#app'); ``` 这段脚本说明了怎样把刚才建立的服务作为名为 `$http` 的全局函数暴露给所有的组件使用。 #### 创建服务层接口 接下来可以基于上面提到的基础客户端构建具体业务场景下的 API 接口调用方法。这里给出一个例子展示如何定义登录功能对应的远程过程调用(RPC): ```typescript // src/apis/user.ts import service from '@/utils/axios'; interface ILoginData {} export function login(data: ILoginData): any { return service({ url: '/login', // 这里应该是实际服务器提供的路径 method: 'post', data }) } ``` 此处介绍了如何利用先前准备好的 Axios 工具类去执行特定类型的HTTP操作,比如 POST 登录验证请求[^4]。 #### 配置开发环境中的代理 当处于本地调试阶段时,可能会遇到跨域资源共享(CORS)的问题。为了避免这种情况发生,推荐采用 Webpack DevServer 提供的功能来进行反向代理设置。编辑 `vite.config.ts` 或者 `.env.development.local` 来指定转发规则: 对于Vite项目,在 vite.config.ts 添 proxy 设置: ```ts // vite.config.ts import { defineConfig } from 'vite' export default defineConfig({ server: { proxy: { '^/api': { target: 'https://example.com/api/', changeOrigin: true, rewrite: path => path.replace(/^\/api/, ''), }, }, }, }) ``` 如果是Webpack项目则在 webpack.dev.conf.js 修改 devServer.proxy 属性: ```js module.exports = { // ... devServer: { host: 'localhost', port: 8080, open: true, hotOnly: false, overlay: { warnings: false, errors: true }, proxy: { '/api': { target: 'http://jsonplaceholder.typicode.com/', // 替换成目标API地址 ws: true, changeOrigin: true, secure: false, pathRewrite: {'^/api' : ''} } } } }; ``` 以上内容解释了如果要解决前后端分离架构下常见的 CORS 错误应该如何调整开发工具链的相关选项[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值