欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

vue的axios配置与api封装

程序员文章站 2022-07-02 16:54:09
...

话不多少,上代码(fetch文件):

import Vue from 'vue'
import axios from 'axios'
import Store from '../vuex/store.js' //运用到Vuex可使用
const QS = require('qs')

/**
 * 开发配置baseUrl
 */
// const PRIVARY_URL = '/quality' // 生产
const PRIVARY_URL = '/dev' // 开发

/**
 *
 * 生产配置baseUrl
 */
const PROXY_URL = '/qualitydev'
axios.defaults.baseURL = process.env.NODE_ENV === 'production' ? PROXY_URL : PRIVARY_URL

axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded'
Vue.prototype.$baseUrls = axios.defaults.baseURL
axios.defaults.timeout = 30000

// 重新请求
axios.defaults.retry = 360
axios.defaults.retryDelay = 10000

let pending = [] // 声明一个数组用于存储每个 ajax 请求的取消函数和ajax标识
let CancelToken = axios.CancelToken
let removePending = (ever) => {
  /**
   * TODO: 对极短时间内相同的重复请求拦截,阻止请求(防止按钮重复点击,发出多次相同请求)
   */
  for (let p in pending) {
    if (pending[p].u === ever.url + '&' + ever.method + '&' + JSON.stringify(ever.params)) { // 当当前请求在数组中存在时执行函数体
      // pending[p].cancle('重复操作') // 执行取消操作
      pending.splice(p, 1) // 把这条记录从数组中移除
    }
  }
}
var vue = new Vue()
// Add a request interceptor

//请求拦截器
axios.interceptors.request.use(
  config => {
   //每个请求都有的默认的参数,可以是登陆之后的用户信息
    const appId = 'QUALITY_WEB'
    let user = (new Vue())._util.getUser()
    if (user) {
      const userKey = user.userKey
      config.params = {
        userKey,
        appId,
        ...config.params
      }
      //请求头封装参数
      config.headers.userId = user.id
      config.headers.token = user.userKey
    } else {
      config.params = {
        appId,
        ...config.params
      }
    }
    removePending(config) // 在一个ajax发送前执行一下取消操作
    config.cancelToken = new CancelToken((c) => {
      // 这里的ajax标识是用请求地址&请求方式&请求参数拼接的字符串,也可以选择其他的一些方式
      pending.push({ u: config.url + '&' + config.method + '&' + JSON.stringify(config.params), cancle: c })
    })
    return config
  },
  error => {
    return Promise.reject(error)
  }
)

// Add a response interceptor
//响应拦截
axios.interceptors.response.use(
  response => { // 如果返回的数据中status不为1,则全局警告
    // ------------------------------------------------------------------------------------------
    removePending(response.config) // 在一个ajax响应后再执行一下取消操作,把已经完成的请求从pending中移除
    // ------------------------------------------------------------------------------------------
    if (response.data && response.data.status !== 1) {
      if (response.data.message) {
        myMessage.warning(response.data.message)
      }
      // 登录失效
      if (response.data.status === 0) {
        Store.commit('SET_USER', null)
        Store.commit('screen_boo', false)
      }
    }
    vue.$loading.hide()
    return response
  },
  error => { // 返回状态码不为200时候的错误处理
    // var RetryNetwork = function () {
    //   let config = error.config
    //   // If config does not exist or the retry option is not set, reject
    //   if (!config || !config.retry) return Promise.reject(error)
    //   // Set the variable for keeping track of the retry count
    //   config.__retryCount = config.__retryCount || 0
    //   // Check if we've maxed out the total number of retries
    //   if (config.__retryCount >= config.retry) {
    //     // Reject with the error
    //     return Promise.reject(error)
    //   }
    //   // Increase the retry count
    //   config.__retryCount += 1
    //   // Create new promise to handle exponential backoff
    //   let backoff = new Promise(resolve => {
    //     setTimeout(() => {
    //       resolve()
    //     }, config.retryDelay || 3000)
    //   })
    //   return backoff.then(function () {
    //     // check config.url and then remove the baseUrl from cinfig.url
    //     let reg = new RegExp(config.baseURL)
    //     config.url = config.url.replace(reg, '')
    //
    //     return axios(config)
    //   })
    // }
    // vue.$loading.button()
    if (error.message === '重复操作') {
      // myMessage.error('请勿多次重复操作')
      setTimeout(() => {
        vue.$loading.hide()
      }, 1000)
    }
    // 有一种可能是断网了
    if (!error.response && error.message !== '重复操作') { // 超时
      myMessage.error('断网--请求超时, ::NET-DISCONNECT')
      // RetryNetwork()
      setTimeout(() => {
        vue.$loading.hide()
      }, 1000)
    }
    if (error && error.response && error.response.status) {
      switch (error.response.status) {
        case 400:
          myMessage.error('请求错误')
          break
        case 401:
          myMessage.error('未授权,请登录')
          break
        case 403:
          myMessage.error('拒绝访问')
          break
        case 404:
          myMessage.error('请求路径出错: 404 NOT FOUND')
          // RetryNetwork()
          break
        case 408:
          myMessage.error('请求超时, ::CODE 408')
          break
        case 500:
          myMessage.error('服务器内部错误')
          break
        case 501:
          myMessage.error('服务未实现')
          break
        case 502:
          myMessage.error('网关错误')
          break
        case 503:
          myMessage.error('服务不可用')
          break
        case 504:
          myMessage.error('网关超时, ::SERVER 504')
          // RetryNetwork()
          break
        default:
          myMessage.error('未知错误', error.response.status)
          break
      }
      setTimeout(() => {
        vue.$loading.hide()
      }, 1000)
    }
    return Promise.reject(error)
  }
)

function transformRequest (data, options) {
  let temp = data
  // 把一个参数对象格式化为一个字符串
  if (!options.isJson) {
    temp = QS.stringify(data)
  }
  // 上传用formData封装
  if (options.isUpload) {
    let formData = new FormData()
    for (let key in data) {
      formData.append(key, data[key])
    }
    temp = formData
  }
  return temp
}

export default axios(url = '', params = {}, method = 'get', options = { isUpload: false, isJson: false }) => {
  if (!params.hideLoading) {
    vue.$loading.show()
  }
  method = method.toLowerCase()
  if (method === 'get') {
    let paramArr = []
    for (let [key, value] of Object.entries(params)) {
      paramArr.push(key + '=' + value)
    }
    if (paramArr.length > 0) {
      url += '?' + paramArr.join('&').replace(/#/g, '%23')
    }
    return new Promise((resolve, reject) => {
      axios
        .get(url)
        .then(
          response => {
            resolve(response.data)
          },
          err => {
            reject(err)
          }
        )
        .catch(error => {
          reject(error)
        })
    })
  } else if (method === 'post') {
    let config = {}
    if (options.isUpload) {
      config = {
        headers: {
          'Content-Type': 'multipart/form-data'
        }
      }
    }
    // should we use type:'application/x-www-form-urlencoded' to send the data?
    params = transformRequest(params, options)
    return new Promise((resolve, reject) => {
      axios
        .post(url, params, config)
        .then(
          response => {
            resolve(response.data)
          },
          err => {
            reject(err)
          }
        )
        .catch(error => {
          reject(error)
        })
    })
  } else if (method === 'put') {
    return new Promise((resolve, reject) => {
      axios
        .put(url, params)
        .then(
          response => {
            resolve(response.data)
          },
          err => {
            reject(err)
          }
        )
        .catch(error => {
          reject(error)
        })
    })
  } else if (method === 'delete') {
    return new Promise((resolve, reject) => {
      axios
        .delete(url)
        .then(
          response => {
            resolve(response.data)
          },
          err => {
            reject(err)
          }
        )
        .catch(error => {
          reject(error)
        })
    })
  } else {
    let error = '传递的参数错误'
    return Promise.reject(error)
  }
}

api层级封装(index文件):
vue的axios配置与api封装

import fetch from './fetch'
// 教师端  首页
import teacherHome from './xxxx'
// 教师端  项目化学习方案定义
import teacherLearn from './xxxxx'
// 教师端  项目化学习课程实例
import teacherCourse from './xxxxx'
// 教师端  实践活动
import teacherPractica from './xxxxxx'
// 教师端  日常评价
import teacherEvaluation from './xxxxxxx'
// 教师端  学生个体评价
import teacherIndividual from './xxxxxx'
// 教师端  平台入口
import teacherPlatform from './xxxxxxxx'
// 教师端 权限管理
import teacherAuthority from './xxxxxxx'
// 导入数据
import guidedData from './xxxxxxxx'
// 学生端
import studentCourse from './xxxxxxx'
// 教师端综评管理
import teacherMament from './xxxxxx.js'
// 教师端学习任务
import teacherStudyTask from './xxxxxxxx.js'
// 教师端体质健康
import teacherHealth from './xxxxxxx.js'
import teacherCreateRecords from './xxxxxxxxxxx'

export default {
  login (deviceId, account, password) {
    return fetch(`/xxxxxx`, { deviceId, account, password }, 'get')
  },
  smsUpdatePhone (id, deviceId, phone, zone, verifyCode, system, appId) { // 绑定手机号
    return fetch('newUser/xxxxxxx', {id, deviceId, phone, zone, verifyCode, system, appId}, 'get')
  },
  sendMsg (phone, zone, system) { // 发送短信
    return fetch('user/xxxxx', {phone, zone, system}, 'get')
  },
  smsLogin (deviceId, phone, zone, verifyCode, system) { // 手机号登录
    return fetch('/newUser/xxxx', {deviceId, phone, zone, verifyCode, system}, 'get')
  },
  getToken (bucketType, fileType) {
    return fetch('file/xxxx', { bucketType, fileType }, 'post')
  },
  qnUpload (key, token, file) {
    return fetch('https://upload.qiniu.com', { key, token, file }, 'post', { isUpload: true })
  },
  findGradeSubjects () {
    return fetch('/school/check/xxxxxxx', {}, 'get')
  },
  findSchoolInfo () {
    return fetch('schoolInfo/check/xxxxxxxx', { }, 'get')
  },
  systemlogin (systemUserId) {
    return fetch('userSystemInfo/xxxxxxx', {systemUserId}, 'post', { isUpload: true })
  },
  ...teacherHome,
  ...teacherLearn,
  ...teacherCourse,
  ...teacherPractica,
  ...teacherEvaluation,
  ...teacherIndividual,
  ...teacherPlatform,
  ...teacherAuthority,
  ...guidedData,
  ...studentCourse,
  ...teacherMament,
  ...teacherStudyTask,
  ...teacherHealth,
  ...teacherCreateRecords
}

某一个页面接口文件:

import fetch from './fetch'

export default {
  // 任务实例
  getCourseTask (type, time) {
    return fetch('course/check/xxxxx', {type, time}, 'get')
  },
  // 开课获取课程列表的接口
  getCourseList (subject) {
    return fetch('course/check/xxxxx', {subject}, 'get')
  },
  // 根据年级学科,获取教师名单
  getGradeSubject (grade, subject, hideLoading = true) {
    return fetch('user/check/xxxxxxxx', {grade, subject, hideLoading}, 'get')
  },
  // 学生导入
  inputStudent (students, grades) {
    return fetch('course/check/xxxxxxxx', {students, grades}, 'post', {isUpload: true})
  },
  // 开课请求
  startCourse (courseId, ownerId, teacherIds, groupCount, studentIds, errorList) {
    return fetch('course/check/xxxxxxxx', {courseId, ownerId, teacherIds, groupCount, studentIds, errorList}, 'post', {isJson: true})
  }

在main.js中全局注册:

...
import axios from '@/http'
...
 Vue.prototype.$http = axios
...