• vueelementadminaxios 用法分析(封装)


    request 库使用了 axios 的手动实例化方法 create 来封装请求,要理解其中的用法,我们需要首先学习 axios 库的用法

    1.axios 基本案例

    普通的 axios 示例

    import axios from 'axios'
    
    const url = 'https://test.youbaobao.xyz:18081/book/home/v2?openId=1234'
    axios.get(url).then(response => {
      console.log(response)
    })

    上述代码可以改为:

    const url = 'https://test.youbaobao.xyz:18081/book/home/v2'
    axios.get(url, { 
      params: { openId: '1234' }
    })

    如果我们在请求时需要在 http header 中添加一个 token,需要将代码修改为:

    const url = 'https://test.youbaobao.xyz:18081/book/home/v2'
    axios.get(url, { 
      params: { openId: '1234' },
      headers: { token: 'abcd' }
    }).then(response => {
      console.log(response)
    })

    如果要捕获服务端抛出的异常,即返回非 200 请求,需要将代码修改为:

    const url = 'https://test.youbaobao.xyz:18081/book/home/v2'
    axios.get(url, { 
      params: { openId: '1234' },
      headers: { token: 'abcd' }
    }).then(response => {
      console.log(response)
    }).catch(err => {
      console.log(err)
    })

    这样改动可以实现我们的需求,但是有两个问题:

    • 每个需要传入 token 的请求都需要添加 headers 对象,会造成大量重复代码
    • 每个请求都需要手动定义异常处理,而异常处理的逻辑大多是一致的,如果将其封装成通用的异常处理方法,那么每个请求都要调用一遍

    2.axios.create 示例

    下面我们使用 axios.create 对整个请求进行重构:

    const url = '/book/home/v2'
    const request = axios.create({
      baseURL: 'https://test.youbaobao.xyz:18081',
      timeout: 5000
    })
    request({
      url, 
      method: 'get',
      params: {
        openId: '1234'
      }
    })

    首先我们通过 axios.create 生成一个函数,该函数是 axios 实例,通过执行该方法完成请求,它与直接调用 axios.get 区别如下:

    • 需要传入 url 参数,axios.get 方法的第一个参数是 url
    • 需要传入 method 参数,axios.get 方法已经表示发起 get 请求

    3.axios 请求拦截器

    上述代码完成了基本请求的功能,下面我们需要为 http 请求的 headers 中添加 token,同时进行白名单校验,如 /login 不需要添加 token,并实现异步捕获和自定义处理:

    const whiteUrl = [ '/login', '/book/home/v2' ]
    const url = '/book/home/v2'
    const request = axios.create({
      baseURL: 'https://test.youbaobao.xyz:18081',
      timeout: 5000
    })
    request.interceptors.request.use(
      config => {
        // throw new Error('error...')
        const url = config.url.replace(config.baseURL, '')
          if (whiteUrl.some(wl => url === wl)) {
            return config
          }
        config.headers['token'] = 'abcd'
        return config
      },
      error => {
        return Promise.reject(error)
      }
    )
    request({
      url, 
      method: 'get',
      params: {
        openId: '1234'
      }
    }).catch(err => {
      console.log(err)
    })

    这里核心是调用了 request.interceptors.request.use 方法,即 axios 的请求拦截器,该方法需要传入两个参数,第一个参数是拦截器方法,包含一个 config 参数,我们可以在这个方法中修改 config 并且进行回传,第二个参数是异常处理方法,我们可以使用 Promise.reject(error) 将异常返回给用户进行处理,所以我们在 request 请求后可以通过 catch 捕获异常进行自定义处理

    4.axios 响应拦截器

    下面我们进一步增强 axios 功能,我们在实际开发中除了需要保障 http statusCode 为 200,还需要保证业务代码正确,上述案例中,我定义了 error_code 为 0 时,表示业务返回正常,如果返回值不为 0 则说明业务处理出错,此时我们通过 request.interceptors.response.use 方法定义响应拦截器,它仍然需要2个参数,与请求拦截器类似,注意第二个参数主要处理 statusCode 非 200 的异常请求,源码如下:

    const whiteUrl = [ '/login', '/book/home/v2' ]
    const url = '/book/home/v2'
    const request = axios.create({
      baseURL: 'https://test.youbaobao.xyz:18081',
      timeout: 5000
    })
    request.interceptors.request.use(
      config => {
        const url = config.url.replace(config.baseURL, '')
        if (whiteUrl.some(wl => url === wl)) {
          return config
        }
        config.headers['token'] = 'abcd'
        return config
      },
      error => {
        return Promise.reject(error)
      }
    )
    
    request.interceptors.response.use(
      response => {
        const res = response.data
        if (res.error_code != 0) {
          alert(res.msg)
          return Promise.reject(new Error(res.msg))
        } else {
          return res
        }
      },
      error => {
        return Promise.reject(error)
      }
    )
    
    request({
      url, 
      method: 'get',
      params: {
        openId: '1234'
      }
    }).then(response => {
      console.log(response)
    }).catch(err => {
      console.log(err)
    })

    5.request 库源码分析

    有了上述基础后,我们再看 request 库源码就非常容易了

    const service = axios.create({
      baseURL: process.env.VUE_APP_BASE_API,
      timeout: 5000
    })
    
    service.interceptors.request.use(
      config => {
        // 如果存在 token 则附带在 http header 中
        if (store.getters.token) {
          config.headers['X-Token'] = getToken()
        }
        return config
      },
      error => {
        return Promise.reject(error)
      }
    )
    
    service.interceptors.response.use(
      response => {
        const res = response.data
    
        if (res.code !== 20000) {
          Message({
            message: res.message || 'Error',
            type: 'error',
            duration: 5 * 1000
          })
          // 判断 token 失效的场景
          if (res.code === 50008 || res.code === 50012 || res.code === 50014) {
            // 如果 token 失效,则弹出确认对话框,用户点击后,清空 token 并返回登录页面
            MessageBox.confirm('You have been logged out, you can cancel to stay on this page, or log in again', 'Confirm logout', {
              confirmButtonText: 'Re-Login',
              cancelButtonText: 'Cancel',
              type: 'warning'
            }).then(() => {
              store.dispatch('user/resetToken').then(() => {
                location.reload()
              })
            })
          }
          return Promise.reject(new Error(res.message || 'Error'))
        } else {
          return res
        }
      },
      error => {
        Message({
          message: error.message,
          type: 'error',
          duration: 5 * 1000
        })
        return Promise.reject(error)
      }
    )
    
    export default service
  • 相关阅读:
    [LC] 939. Minimum Area Rectangle
    [LC] 1110. Delete Nodes And Return Forest
    [LC] 1057. Campus Bikes
    [LC] 528. Random Pick with Weight
    [LC] 341. Flatten Nested List Iterator
    oracle获取本月第一天和最后一天及Oracle trunc()函数的用法
    监控concurrent 正在执行的sql
    UTL_FILE 的用法
    查询EBS在线用户SQL(R12)
    ORACLE EBS BOM 展开(使用标准程序bompexpl.exploder_userexit展开)
  • 原文地址:https://www.cnblogs.com/pwindy/p/15568394.html
Copyright © 2020-2023  润新知