计算机系统应用教程网站

网站首页 > 技术文章 正文

axios封装应用和vite跨域配置 axios封装详解

btikc 2024-10-17 08:36:48 技术文章 22 ℃ 0 评论

axios封装

虽然vite在很多配置方面和vue-cli极其相似,但是区别的地方还是需要注意的。在给axios封装过程中一般需要区分开发或者生产环境,因为开发与生产环境对应的服务器不一致,比如接口地址。

vue-cli内置的process.env.NODE_ENV的可以判断当前的环境是development还是production,而vite使用的方法是import.meta.env.NODE_ENV,所以针对vue-cli和vite环境下的封装需要注意这点:

// src/request/axios.js
import axios from 'axios'
import qs from 'qs'
// import router from '@/router'//路由文件
// import { Message } from 'element-ui'
let api_base_url = ''
// vite
if (import.meta.env.NODE_ENV === 'development') {
  api_base_url = 'https://client.doubilm.com'
} else if (import.meta.env.NODE_ENV === 'production') {
  api_base_url = 'https://client.doubilm.com'
}
// 如果是vue-cli
//if (process.env.NODE_ENV === 'development') {
//  api_base_url = 'https://client.doubilm.com'
//} else if (import.meta.env.NODE_ENV === 'production') {
//  api_base_url = 'https://client.doubilm.com'
//}

/*  防止请求重复
1. 我们需要对所有正在进行中的请求进行缓存。在请求发起前判断缓存列表中该请求是否正在进行,如果有则取消本次请求。
2.在任意请求完成后,需要在缓存列表中删除该次请求,以便可以重新发送该请求
*/

//正在请求的API队列
let requestList = []
/**
 * @name:  阻止请求
 * @param {array} requestList 当前API请求队列
 * @param {string} currentUrl  当前请求API
 * @param {function} cancelFn  请求中断函数
 * @param {string} errorMsg   中断错误信息
 */
const stopRepeatRequest = (requestList, currentUrl, cancelFn, errorMsg) => {
  const errorMessage = errorMsg || '请求出错拥堵'
  for (let i = 0; i < requestList.length; i++) {
    if (requestList[i] === currentUrl) {
      cancelFn(errorMessage)
      return
    }
  }
  // 将当前请求加入执行队列
  requestList.push(currentUrl)
}
/**
 * @name:  请求完成后从队列删除当前请求
 * @param {array} requestList 当前API请求队列
 * @param {string} currentUrl  当前请求API
 */
const allowRequest = (requestList, currentUrl) => {
  for (let i = 0; i < requestList.length; i++) {
    if (requestList[i] === currentUrl) {
      requestList.splice(i, 1)
      break
    }
  }
}
let instance = axios.create({
  timeout: 1000 * 80,
  baseURL: api_base_url,
  // headers: {
  //   'Content-Type': 'application/json;charset=UTF-8',
  // },
})
// instance.defaults.headers.common['Access-Control-Allow-Origin'] = '*';
// instance.defaults.responseType = 'json'
// instance.defaults.withCredentials = true
instance.defaults.transformRequest = [
  data => {
    return qs.stringify(data)
  }
]
instance.defaults.validateStatus = function () {
  // return status >= 200 && status < 400; // 200- 399  resolve  其他状态码 reject
  // 如果在响应拦截设置了状态码判断,这里设置返回 true
  return true
}
// 请求拦截器
instance.interceptors.request.use(
  config => {
    // 设置cancelToken
    let cancelFn = null;
    config.cancelToken = new axios.CancelToken(function (c) {
      cancelFn = c
    })
    //阻止重复请求
    stopRepeatRequest(requestList, config.url, cancelFn, `不要连续请求:${config.url},速度太快了`)
    //{url: "/slides", method: "get", headers: {…}, baseURL: "http://api.hzwlb.org", transformRequest: Array(1), responseType: "json",…}
    return config
  },
  error => {
    // Message.error({ message: '请求超时!' })
    // console.log('请求超时!');
    return Promise.reject(error)
  }
)
// 响应拦截器即异常处理
// 服务器 Response 对象
instance.interceptors.response.use(
  response => {
    //不得重复发送
    setTimeout(() => {
      allowRequest(requestList, response.config.url), 1000
    })
    // {data: {…}, status: 200, statusText: "OK", headers: {…}, config: {…}, request:{…}}
    let data = response.data     //响应的数据部分(服务器返回部分)
    let status = response.status  //标准状态码
    if (status === 200) {  //如果响应正常则放行 数据
      return Promise.resolve(data)
    }
    else if (status >= 400 && status <= 499) {
      // Message.error({ message: '客户端请求错误!' })
      console.log('客户端请求错误码:', status);
      return
    }
    else {
      //其他错误
      // Message.error({ message: response.statusText })
      // console.log('服务器错误,错误码:', status);
      // return Promise.reject(response)
      if (axios.isCancel(thrown)) {
        console.log(thrown.message);
      } else {
        return Promise.reject(response)
      }
    }
  },
  error => {
    console.log('响应错误信息:')
    console.log(error.message)
  }
)
let api = {}
api.get = function (url) {
  return new Promise((resolve, reject) => {
    instance
      .get(url)
      .then(response => {
        resolve(response)
      })
      .catch(error => {
        reject(error)
      })
  })
}
api.post = function (url, data) {
  return new Promise((resolve, reject) => {
    instance
      .post(url, data)
      .then(response => {
        resolve(response)
      })
      .catch(error => {
        reject(error)
      })
  })
}
export default api

增加了对重复请求的处理

API调用

再和上面同级目录内创建一个聚合API的文件api.js

import api from "./axios.js"
export const getEmoticon = () => api.get(`/api/emoticon/recommend/list`)

组件内再引入相关的API

import { getEmoticon } from "../request/api.js";

async function Emoticon() {
  let result = await getEmoticon();
}

vite跨域的配置(代理跨域)

import { defineConfig } from 'vite'

const { resolve } = require('path')

import vue from '@vitejs/plugin-vue'
// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue()], // 配置需要使用的插件列表,这里将vue添加进去
  // 配置文件别名 vite1.0是/@/  2.0改为/@
  // 这里是将src目录配置别名为 /@ 方便在项目中导入src目录下的文件
  resolve: {
    alias: {
      "/@": resolve(__dirname, 'src')
    }
  },
  // 强制预构建插件包
  optimizeDeps: {
    include: ['axios'],
  },
  // 打包配置
  build: {
    target: 'modules',
    outDir: 'dist', //指定输出路径
    assetsDir: 'assets', // 指定生成静态资源的存放路径
    minify: 'terser' // 混淆器,terser构建后文件体积更小
  },
  // 本地运行配置,及反向代理配置
  server: {
    cors: true, // 默认启用并允许任何源
    open: true, // 在服务器启动时自动在浏览器中打开应用程序
    port: 8080,
    //反向代理配置,注意rewrite写法,开始没看文档在这里踩了坑
    proxy: {
      '^/api': {
        target: 'https://client.doubilm.com',   //代理接口
        changeOrigin: true,
        rewrite: (path) => path.replace(/^\/api/, '')
      }
    }
  }
})

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表