Axios封装

29 篇文章 1 订阅
5 篇文章 0 订阅

一、全局loading效果

        通常在vue项目中使用最多的第三方请求库就是axios了,以此来实现与后台的数据交互。而在我们请求后台数据的时候,响应时间是不确定的,用户可能不知道我点了按钮之后它“怎么”了?所以我们通常需要一个loading效果,来告诉用户:我点了按钮之后又反应了,它让我等一会儿。

        但如果我们在每次请求的时候都去手动加一个loading效果,这无疑是很麻烦的,包括后期的维护成本也是很高的,而且当有多次请求同时触发时,相应的会多次触发loading。
        因此我们需要对loading进行统一封装管理

1、对axios库进行二次封装

需求分析:

  • 当发送请求时触发loading效果,在请求结束后移除loading
  • 当存在多个请求时需要确保只有一个loading,不能出现多个
  • 当一次请求完成后,立即发起了另外一个请求,此时会出现loading闪烁的情况,需要进行防抖处理
  • 所有请求的loading效果需要可配置,默认每个请求都有loading效果,可配置请求无loading
  • 默认所有loading的效果是body覆盖于之上的,可配置覆盖指定元素之上

说明:

  • 主库:axios
  • loading效果实现:ElementUI的loading组件
  • 错误消息提示:ElementUI的Message组件
  • 防抖:lodash的debounce防抖
  • showLoading:设置是否显示loading
  • loadingTarget:设置loading效果覆盖的元素

代码实现:

import axios from 'axios'
import { Message, Loading } from 'element-ui'
import _lodash from 'lodash'
import { baseURL } from '../common/env.js'

// loading对象
let loading
// 当前正在请求的数量
let underwayRequestCount = 0

// 显示loading
const showLoading = target => {
  // 后面这个判断很重要,因为关闭时加了抖动,此时loading对象可能还存在,
  // 但underwayRequestCount已经变成0.避免这种情况下会重新创建个loading
  if (underwayRequestCount === 0 && !loading) {
    loading = Loading.service({
      lock: true,
      text: 'Loading...',
      background: 'rgba(255, 255, 255, 0.5)',
      target: target || 'body'
    })
  }
  underwayRequestCount++
}

// 隐藏loading
const hideLoading = () => {
  underwayRequestCount--
  underwayRequestCount = Math.max(underwayRequestCount, 0) // 做个保护
  if (underwayRequestCount === 0) {
    // 关闭loading
    toHideLoading()
  }
}

// 防抖:将 300ms 间隔内的关闭 loading 合并为一次。防止连续请求时, loading闪烁的问题。
let toHideLoading = _lodash.debounce(() => {
  loading.close()
  loading = null
}, 300)

// 请求成功
const requestSuccess = config => {
  console.log(config)
  // 判断当前请求是否设置了不显示Loading
  if (config.headers.showLoading !== false) {
    showLoading(config.headers.loadingTarget)
  }
  // 获取token,在请求中添加 token
  let token = ''
  if (sessionStorage.getItem('wti-manager-token')) {
    token = sessionStorage.getItem('wti-manager-token')
    token = token ? '' + token : ''
  }
  config.headers.Authorization = token
  return config
}

// 请求失败
const requestFault = err => {
  // 判断当前请求是否设置了不显示Loading(不显示自然无需隐藏)
  if (err.config.headers.showLoading !== false) {
    hideLoading()
  }
  Message.error('请求超时!')
  return Promise.resolve(err)
}

// 响应成功
const responseSuccess = response => {
  // 判断当前请求是否设置了不显示Loading(不显示自然无需隐藏)
  if (response.config.headers.showLoading !== false) {
    hideLoading()
  }
  // 如果用户登录过期了
  if (response.data.code === 401) {
    Message({
      message: '登陆认证已过期,请重新登陆!',
      type: 'warning'
    })
    //  如果不是请求成功
  } else if (response.data.code !== 200 && response.data.code !== 201) {
    Message({
      message: response.data.msg,
      type: 'warning'
    })
  }
  return response.data
}

// 响应失败
const responseFault = error => {
  // 判断当前请求是否设置了不显示Loading(不显示自然无需隐藏)
  if (error.config.headers.showLoading !== false) {
    hideLoading()
  }
  // 对错误数据进行处理
  if (error.response && error.response.data && error.response.data.message) {
    let jsonObj = JSON.parse(error.response.data.message)
    Message.error(jsonObj.message)
  } else {
    Message.error(error.message)
  }
  return Promise.reject(error)
}

// 设置axios的默认项
axios.defaults.baseURL = baseURL
axios.defaults.timeout = 40000
axios.interceptors.request.use(requestSuccess, requestFault)
axios.interceptors.response.use(responseSuccess, responseFault)

// 生成 axios 对象
const generateAxios = config => {
  const newAxios = axios.create(config)
  newAxios.interceptors.request.use(requestSuccess, requestFault)
  newAxios.interceptors.response.use(responseSuccess, responseFault)
  return newAxios
}

const post = (url, data, headers) => {
  return axios({
    method: 'post',
    url,
    headers,
    data
  })
}

const get = (url, params, headers) => {
  return axios({
    method: 'post',
    url,
    headers,
    params
  })
}

export {
  generateAxios,
  post,
  get
}

2、使用

默认全屏loading

      // passwordLogin:封装过的方法
      /*
        passwordLogin (payload, headers) {
          return post('/wkbbackend/login/password', payload, headers)
        }
      */
      // 普通请求
      this.$http.passwordLogin(data).then(res => {
        if (res.code === 200) {
          const Authorization = res.data.login.Authorization
          sessionStorage.setItem('wti-manager-token', Authorization)
          this.$message.success('登录成功')
        } else {
          this.$message.error('登录失败')
        }
      })

不需要显示loading

      // 设置不显示loading
      this.$http.passwordLogin(data, {showLoading: false}).then(res => {
        if (res.code === 200) {
          const Authorization = res.data.login.Authorization
          sessionStorage.setItem('wti-manager-token', Authorization)
          this.$message.success('登录成功')
        } else {
          this.$message.error('登录失败')
        }
      })

loading指定显示在某个dom元素上

      // 设置loading显示的dom
      this.$http.passwordLogin(data, {loadingTarget: '#loading-box'}).then(res => {
        if (res.code === 200) {
          const Authorization = res.data.login.Authorization
          sessionStorage.setItem('wti-manager-token', Authorization)
          this.$message.success('登录成功')
        } else {
          this.$message.error('登录失败')
        }
      })

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值