0
点赞
收藏
分享

微信扫一扫

axios的两种封装方式(也就是项目中请求接口的两种方式)

爱做梦的老巫婆 2022-03-25 阅读 122

1·axios的第一种封装

在main.js中进行全局注册

import httpRequest from '@/utils/httpRequest'
Vue.prototype.$http = httpRequest 

httpRequest.js中的文件

import axios from 'axios'
import qs from 'qs'
import merge from 'lodash/merge'
import { clearLoginInfo } from '@/utils'
import { Message } from 'element-ui'

let tokenBoolean = true
const http = axios.create({
  timeout: 1000 * 30,
  withCredentials: true,
  headers: {
    'Content-Type': 'application/json; charset=utf-8'
  }
})

/**
 * 请求拦截
 */
http.interceptors.request.use(config => {
  var token = localStorage.getItem('token')
  config.headers['token'] = token
  if (token === null || token === '' || token === undefined) {
    clearLoginInfo()
    tokenBoolean = false
  } else {
    tokenBoolean = true
  }
  if (config.method === 'get' && tokenBoolean) {
    config.paramsSerializer = function(params) {
      return qs.stringify(params, { arrayFormat: 'repeat' })
    }
  }
  return config
}, error => {
  return Promise.reject(error)
})

/**
 * 响应拦截
 */
var errorResponse = false
http.interceptors.response.use(response => {
  // endLoading()
  if (response.data && response.data.code !== 0 && response.data.code !== 401) {
    if (response && response.data && response.data.msg && !response.data.msg.includes('targetId')) {
      Message({
        message: response.data.msg || 'Error',
        type: 'error',
        duration: 1 * 1000
      })
    }
  }
  if (response.data && response.data.code === 401 && tokenBoolean) {
    Message({
      message: response.data.msg || 'Error',
      type: 'error',
      duration: 1 * 1000
    })
    clearLoginInfo()
    tokenBoolean = false
  }
  return response
}, error => {
  errorResponse = true
  // console.log('errorResponse',errorResponse)
  if (error.message.includes('timeout')) {
    Message({
      message: '请求超时,请稍后再试',
      type: 'error',
      duration: 1 * 1000
    })
    return Promise.reject(error)
  }
  Message({
    message: '网络连接失败,请稍后再试',
    type: 'error',
    duration: 1 * 1000
  })
  return Promise.reject(error)
})

/**
 * 请求地址处理
 * @param {*} actionName action方法名称
 */
http.adornUrl = (actionName) => {
  // 非生产环境 && 开启代理, 接口前缀统一使用[/proxyApi/]前缀做代理拦截!
  return (process.env.NODE_ENV !== 'production' && process.env.OPEN_PROXY ? '/proxyApi/' : process.env.VUE_APP_BASE_URL) + actionName
}

/**
 * get请求参数处理
 * @param {*} params 参数对象
 * @param {*} openDefultParams 是否开启默认参数?
 */
http.adornParams = (params = {}, openDefultParams = true) => {
  var defaults = {
    't': new Date().getTime()
  }
  return openDefultParams ? merge(defaults, params) : params
}

/**
 * post请求数据处理
 * @param {*} data 数据对象
 * @param {*} openDefultdata 是否开启默认数据?
 * @param {*} contentType 数据格式
 *  json: 'application/json; charset=utf-8'
 *  form: 'application/x-www-form-urlencoded; charset=utf-8'
 */
http.adornData = (data = {}, openDefultdata = true, contentType = 'json') => {
  var defaults = {
    't': new Date().getTime()
  }
  data = openDefultdata ? merge(defaults, data) : data
  return contentType === 'json' ? JSON.stringify(data) : qs.stringify(data)
}

export default http

get请求的使用

 this.$http({
        url: this.$http.adornUrl('/restinfo/restInfoIsUpdate'),
        method: 'get',
        params: this.$http.adornParams({ restId:restId })
      }).then(({ data }) => {
       console.log(data.data)
      })

post请求的使用

 this.$http({
        url: this.$http.adornUrl('/rest/complain/edit'),
        method: 'post',
        data: this.$http.adornData({
          id: row.id,
          Result: '1',
          complainStatus: 1
        })
      }).then(({ data }) => {
        if (data.data && data.code === 0) {
          console.log(data.data)
        }
      })

2·axios的第二种封装方式

在工具文件夹中定义一个require.js(axios的封装)

//1. 导入axios对象
import axios from 'axios'
import { Message } from 'element-ui'
import { clearLoginInfo } from '@/util'
import qs from 'qs'
import store from '../store'

// 取消重复请求一个接口
const removeCommonPending = config => {
  for (const k in store.state.axiosPromiseCancel0) {
    if (store.state.axiosPromiseCancel[k].u === config.url + '&' + config.method) {
      // 当前请求在数组中存在时执行函数体
      store.commit('clearCommonAxiosPromiseCancel', k)
    }
  }
}

var tokenBoolean
const Server = axios.create({
  headers: {
    'content-type': 'application/json; charset=UTF-8',
  },
  timeout: 6000,
})
// 请求拦截器
Server.interceptors.request.use(
  config => {
    // 给管理后台的接口设置header头,添加token属性
    let token = localStorage.getItem('token')
    if (token) {
      config.headers['token'] = token //给header头添加token值
      tokenBoolean = true
    } else {
      clearLoginInfo()
      tokenBoolean = false
    }
    if (config.method === 'get' && tokenBoolean) {
      config.paramsSerializer = function(params) {
        return qs.stringify(params, { arrayFormat: 'repeat' })
      }
    }
    removeCommonPending(config)
    config.cancelToken = new axios.CancelToken(cancel => {
      store.commit('setAxiosPromiseCancelArr', { u: config.url + '&' + config.method, f: cancel })
    })
    return config
  },
  error => {
    // 出现异常
    return Promise.reject(error)
  }
)

// 响应拦截器
var errorResponse = false
// 当页面多个错误弹窗时只弹一个
let messageInstance = null
const resetMessage = options => {
  //关闭上一个弹窗,继续下一个弹窗
  if (messageInstance) {
    messageInstance.close()
  }
  messageInstance = Message(options)
}
Server.interceptors.response.use(
  response => {
    if (
      // 如果接口返回文件流则直接返回报文体
      response.headers['content-type'].indexOf('application/vnd.ms-excel') > -1 &&
      !response.data.hasOwnProperty('responseCode')
    ) {
      return response.data
    }
    if (response.data && response.data.code !== 0 && response.data.code !== 401) {
      resetMessage({
        message: response.data.msg || 'Error',
        type: 'error',
        duration: 1 * 1000,
      })
      return
    }
    if (response.data && response.data.code === 401 && tokenBoolean) {
      resetMessage({
        message: response.data.msg || 'Error',
        type: 'error',
        duration: 1 * 1000,
      })
      clearLoginInfo()
      tokenBoolean = false
      return
    }

    // 后台正常响应的状态,如果是200, 说明后台处理没有问题
    if (response.status == 200) {
      response.data = cleanData(response.data)
      if (response.data.code === 401) {
        clearLoginInfo()
        tokenBoolean = false
      } else if (response.data && response.data.code !== 0) {
        resetMessage({
          message: response.data.msg || 'Error',
          type: 'error',
          duration: 1 * 1000,
        })
        return response.data
      } else {
        return response.data
      }
    }
    return response
  },
  error => {
    if (axios.isCancel(error)) {
      // 为了终结promise链  就是实际请求  不会走到.catch(rej=>{});这样就不会触发错误提示之类了
      return new Promise()
    }
    errorResponse = true
    if (error.message.includes('timeout')) {
      // 判断请求异常信息中是否含有超时timeout字符串
      resetMessage({
        message: '请求超时,请稍后再试',
        type: 'error',
        duration: 1 * 1000,
      })
      return Promise.reject(error) // reject这个错误信息
    }
    resetMessage({
      message: '网络连接失败,请稍后再试',
      type: 'error',
      duration: 1 * 1000,
    })
    return Promise.reject(error)
  }
)

function cleanData(data) {
  if (data.constructor === Array) {
    //   数组 遍历数组
    data.forEach(element => {
      cleanData(element)
    })
  } else if (data.constructor === Object) {
    //   对象 遍历对象内的字段
    Object.keys(data).forEach(function(key) {
      // 可进行逻辑判断,或者重新赋值
      //   console.log(key, data[key])
      // 如果是字段值是数组或对象 则进入递归
      if (data[key].constructor === Array || data[key].constructor === Object) {
        cleanData(data[key])
      } else {
        if (key === 'hour') {
          data[key] = parseInt(data[key])
        }
      }
    })
  }
  return data
}

export default Server 

在工具文件夹中定义一个http.js(请求方式的封装)

import request from './require'
import qs from 'qs'
var baseURL = ''
var baseUrl2 = ''
if (process.env.NODE_ENV === 'production') {
  baseURL = `${window.location.origin}/api`
  baseUrl2 = `${window.location.origin}/api`
} else {
  baseURL = 'http://192.168.2.24:8089/api'
  baseUrl2 = 'http://192.168.2.24:8089/api'
}
const http = {
  /**
   * methods: 请求
   * @param url 请求地址
   * @param params 请求参数
   */
  baseURL: baseURL,
  baseUrl2: baseUrl2,

  get(url, params, responseType) {
    const config = {
      method: 'get',
      url: url,
    }
    if (params) config.params = params
    if (responseType) config.responseType = responseType
    params === 'json' ? JSON.stringify(params) : qs.stringify(params)

    return request(config)
  },
  post(url, params) {
    const config = {
      method: 'post',
      url: url,
    }
    if (params) config.data = params
    return request(config)
  },
  put(url, params) {
    const config = {
      method: 'put',
      url: url,
    }
    if (params) config.params = params
    return request(config)
  },
  delete(url, params) {
    const config = {
      method: 'delete',
      url: url,
    }
    if (params) config.params = params
    return request(config)
  },
}
//导出
export default http

在api的文件夹下,封装好每一个接口的请求,在这举几个例子

get请求:
  getMenuDataList(params) {
    return http.get(`${baseUrl}/sys/menu/list`, params)
  },

   getScheduleLogInfo(params) {
    return http.get(`${baseUrl}/sys/scheduleLog/info/${params}`)
  },

post请求:
   getAlarmList(params) {
    return http.post(`${baseUrl}/restAlarm/getAlarmList`, params)
  },
    
  deleteRoleDataList(params) {
    return http.post(`${baseUrl}/sys/role/delete/${params}`)
   }
响应数据是文件流的形式:
getEneryinfolistExcel(params) {
    return http.get(`${baseUrl}/v1/restenergydayrecord/energyConsumptionDown`, params, 'blob')
  },

在组件中的使用:

get请求:

import api from '@/api/data'
 api.getMenuDataList(this.dataForm).then(res => {
          if (res.code == '0' || res.code == 0) {
           console.log(res)
          }
        })


 api.getScheduleLogInfo(id).then(({ data }) => {
        if (data && data.code === 0) {
          this.$alert(data.log.error)
        }
     }

post请求:
import api from '@/api/data'
api.getAlarmList(this.dataForm).then(res => { console.log(res)}

 api.deleteRoleDataList(id).then(({ data }) => {
        if (data && data.code === 0) {
          this.$alert(data.log.error)
        }
     }



响应数据是文件流的形式:
import api from '@/api/data'
  api.getEneryinfolistExcel(params).then(res => {
        const blob = new Blob([res], { type: 'application/vnd.ms-excel' })
        const fileName = '能耗信息.xlsx'
        if ('download' in document.createElement('a')) {
          // 不是IE浏览器
          const url = window.URL.createObjectURL(blob)
          const link = document.createElement('a')
          link.style.display = 'none'
          link.href = url
          link.setAttribute('download', fileName)
          document.body.appendChild(link)
          link.click()
          document.body.removeChild(link) // 下载完成移除元素
          window.URL.revokeObjectURL(url) // 释放掉blob对象
        } else {
          // IE 10+
          window.navigator.msSaveBlob(blob, fileName)
        }
      })
举报

相关推荐

0 条评论