前端必备知识点–封装request请求

这是我参与8月更文挑战的第10天,活动详情查看:8月更文挑战

背景

本文所说的request请求即前端请求后端数据所用到的request请求,前后端的交互由来已久,什么jsonp了,ajax了,方式有很多中,今天我就说目前在项目中真正用到的东西,也就是基于axios封装的request请求。下面上代码,一步步的来分析

import axios from 'axios'
import store from '@/store'
import storage from 'store'
import notification from 'ant-design-vue/es/notification' //antdesign中的通知提醒框,如果你用的elementui可以自行更换
import qs from 'qs' //qs库,作用:将url中的参数转化为对象,将对象转为url参数形式
import { ACCESS_TOKEN } from '@/store/mutation-types' // 项目中的token
// 创建 axios 实例
const request = axios.create({
  // API 请求的默认前缀
  baseURL: process.env.VUE_APP_PREVIEW === 'true' ? '/api' : process.env.VUE_APP_API_BASE_URL,
  timeout: 30000 // 请求超时时间
})

// request interceptor
request.interceptors.request.use(config => {
  const token = storage.get(ACCESS_TOKEN)
  // 如果 token 存在
  // 让每个请求携带自定义 token 请根据实际情况自行修改
  if (token) {
    config.headers['Authorization'] = token
  }
  return config
},
error => {
  // do something with request error
  console.log(error) // for debug
  return Promise.reject(error)
})

// response interceptor
request.interceptors.response.use(
  response => {
    // return response.data //可以不做任何处理,在这里了直接返回请求会的结果
    const res = response.data || {}
    if (!res.success) {
      // 401: Unauthorized
      if (res.code === 401) {
        notification.error({
          key: 'Unauthorized',
          message: '错误',
          description: '身份验证失败,请重新登录!'
        })
        // 从 localstorage 获取 token
        const token = storage.get(ACCESS_TOKEN)
        if (token) {
          store.dispatch('Logout').then(() => {
            window.location.reload()
          })
        }
      }

      return Promise.reject(response.data)
    } else {
      return res
    }
  },
  error => {
    return Promise.reject(error)
  }
)

export default {
  /**
   *
   * @param {String} url
   * @param {Object} data
   * @param {String} isForm
   * @param {Object} config
   *
   * 这里是通用请求
   * 如果需要特殊的配置在config中配置
   *
   */
  post (url, data, isForm, config = {}) {
    if (isForm === 'FORM') {
      const formHeaders = {
        // 'X-Requested-With': 'XMLHttpRequest',
        'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8'
      }
      const transformRequest = data =>
        qs.stringify(data, {
          encode: false,
          allowDots: true,
          arrayFormat: 'indices'
        })
      config.transformRequest = config.transformRequest ? [transformRequest, ...config.transformRequest] : [transformRequest]

      config = { headers: formHeaders, ...config }
    }
    // 文件上传
    if (isForm === 'FILE') {
      const formHeaders = {
        'Content-Type': 'multipart/form-data'
      }
      config = { headers: formHeaders, ...config }
      const forms = new FormData()
      forms.append('file', data)
      data = forms
    }
    return request.post(url, data, config)
    //return request.post(url, data, config).then(res => res).catch(e => e),这里的处理和上边的不同是因为上面没做处理的结果return出来的promise对象,做了处理就return出来的是一个经过处理的对象,
  },
  /**
   *
   * @param {String} url
   * @param {Object} params
   */
  get (url, params, config) {
    return request.get(url, { params: params }, config)
    //retrun request.get(url, { params: params }, config)//同上
  }
}

复制代码

难点

  • 这就是一个正常的封装request请求的过程,足以应对日常的前端开发任务,上述中之所以return request可以经过.then().catch()处理,也可以不经过,这么做的原因是为了应对下面的两种场景,一种是用async await来调用接口,一种是用接口名().then().catch()来调用接口

  • 如果你喜欢用async await来请求接口,那么你就用后者,如果你喜欢用接口名().then().catch()来请求接口那你就用前者。

  • 当然,如果你用后者封装return request也可以用接口名().then().catch()形式来调用接口,但是这时候不论后端返回的结果是成功还是失败都会进入到.then()中,而不会到.catch(),但切记如果你用了return request.post(url, data, config),那你再使用async await就会出错,因为此时return的的一个promise对象,可能是个异常,而async await中没有catch操作,但如果你非要这样用也不是不行,记得在使用async await的时候加上try…catch…

async updateStatus () {

    //当request封装的时候没用.then().catch()处理,想用async await 就这样写
    try {
        const data = await updateSysOrgOperatorsStatus()
        this.$message.success(data.data.message)
    } catch (error) {
        this.$message.error(error.message)
    }

    //reques封装的时候用了.then().catch(),async await就可以如下这样正常使用
    const data = await updateSysOrgOperatorsStatus()
    if (data.success) {
        this.$message.success(data.data.message)
    } else {
        this.$message.error(data.message)
    }

    //reques封装的时候不加.then().catch()就可以如下这样正常使用
    updateSysOrgOperatorsStatus().then(res => {
            this.$message.success(res.message)
        }).catch(err => {
            this.$message.error(err.message)
        })
},
复制代码

总结

我个人比较建议用 return request.post(url, data, config),也就是前者,这样看起来简单,用起来也方便,但听一个大佬说还是用后者比较好

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享