• request.js封装


    import Vue from 'vue'
    import router from '@/router'
    import store from '@/store'
    import axios from 'axios'
    import { Message } from 'element-ui'

    const popupErrorMessage = (function popupErrorMessage() {
      const cacheMessage = []
      return function(message) {
        if (!message) {
          return
        }
        if (cacheMessage.indexOf(message) !== -1) {
          return
        }
        Message.error(message)
        cacheMessage.push(message)
        const timeoutId = setTimeout(() => {
          cacheMessage.splice(cacheMessage.indexOf(message), 1)
          clearTimeout(timeoutId)
        }, 1000)
      }
    })()

    Vue.prototype.$http = axios

    const CancelToken = axios.CancelToken
    class PendingRequest {
      constructor() {
        /** @type { Map<string, import('axios').Canceler> } */
        this.pendingMap = new Map()
      }

      /**
       * 发起新的请求前,清除重复请求,并生成新的请求token
       * @param {string} url - 请求的url做为唯一key
       * @returns {import('axios').CancelToken}}
       */
      cancelToken(url) {
        const { pendingMap } = this
        const key = url.split('?')[0]
        if (pendingMap.has(key)) {
          pendingMap.get(key)('取消重复请求')
        }
        return new CancelToken(cancel => {
          pendingMap.set(key, cancel)
        })
      }

      cancelAllToken() {
        const { pendingMap } = this
        pendingMap.forEach(cancelToken => cancelToken('取消重复请求'))
        pendingMap.clear()
      }

      /**
       * 删除已完成的请求token
       * @param {string} url - 请求的url做为唯一key
       */
      delete(url) {
        const key = url.split('?')[0]
        this.pendingMap.delete(key)
      }
    }

    const pendingRequest = new PendingRequest()

    const request = axios.create({
      baseURL: process.env.VUE_APP_URL,
    })

    request.interceptors.request.use(
      config => {
        if (!config.noCancelPendingRequest) {
          config.cancelToken = pendingRequest.cancelToken(config.url)
        }

        const token = localStorage.getItem('token')
        if (token) {
          config.headers.token = token // 请求头部添加token
        }

        return config
      },
      error => {
        return Promise.reject(error)
      },
    )

    request.interceptors.response.use(
      response => {
        const { config, data } = response
        pendingRequest.delete(config.url)

        if (data.respCode === '0000' || data.respCode === '200') {
          return Promise.resolve(data)
        }
        const errorMessage = getCustomErrorMessage(data.respCode || data.status)
        if (errorMessage === false) {
          console.error(`接口响应错误: ${config.url}\n响应内容: ${data}`)
        }
        if (!process.env.production) {
          console.warn(
            `error_code: ${data.respCode},error_message: ${data.respMsg}`,
          )
        }

        !config.noHandleErrorMessage &&
          popupErrorMessage(errorMessage || data.respMsg || data)

        return Promise.reject(data)
      },
      error => {
        const { response, config = {} } = error
        if (response) {
          const errorMessage = getHttpErrorMessage(response.status)
          errorMessage && popupErrorMessage(errorMessage)
          return Promise.reject({
            message: errorMessage,
            respCode: response.status,
          })
        } else {
          if (config.noHandleErrorMessage) {
            // 不处理错误消息
            return Promise.reject(error)
          } else if (error.message.includes('timeout')) {
            // 请求超时或者网络有问题
            popupErrorMessage('请求超时!请检查网络是否正常')
          } else if (error.message.includes('Network Error')) {
            popupErrorMessage('网络连接错误')
          } else if (error.message === '取消重复请求') {
            // 取消重复请求 不做处理
            return Promise.reject({})
          } else {
            popupErrorMessage('请求失败,请检查网络是否已连接')
          }
        }
        return Promise.reject(error)
      },
    )

    function getHttpErrorMessage(code) {
      switch (code) {
        case 404:
          return '网络请求不存在'
        case 503:
          return '服务器目维护中'
        case 500:
          return '服务器内部错误'
      }
    }

    function getCustomErrorMessage(code) {
      if (!code) {
        return false
      }
      switch (code.toString()) {
        case '403':
          handleCustom403Error()
          return '登录已失效,请重新登录'
        case '1003':
          return '没有记录被修改'
        case '1006':
          return '没有记录被删除'
      }
    }

    function handleCustom403Error() {
      pendingRequest.cancelAllToken()
      store.commit('CLEAR_VIEW_TAG')
      if (localStorage.getItem('token')) {
        localStorage.clear()
        router.push('/login')
      }
    }

    export function cancelToken(url) {
      const { pendingMap } = pendingRequest
      const key = url.split('?')[0]
      if (pendingMap.has(key)) {
        pendingMap.get(key)('取消重复请求')
      }
    }

    export default function(url, params = {}, config = {}) {
      return request.post(url, params, config).catch(error => {
        !process.env.production && console.log(error)
        return Promise.reject(error)
      })
    }
  • 相关阅读:
    【BZOJ 3090】 树形DP
    【BZOJ 2323】 2323: [ZJOI2011]细胞 (DP+矩阵乘法+快速幂*)
    【BZOJ 1019】 1019: [SHOI2008]汉诺塔 (DP?)
    【BZOJ 3294】 3294: [Cqoi2011]放棋子 (DP+组合数学+容斥原理)
    【BZOJ 3566】 3566: [SHOI2014]概率充电器 (概率树形DP)
    【BZOJ 2121】 (字符串DP,区间DP)
    【BZOJ 4305】 4305: 数列的GCD (数论)
    【UOJ 179】 #179. 线性规划 (单纯形法)
    【BZOJ 4568】 4568: [Scoi2016]幸运数字 (线性基+树链剖分+线段树)
    【BZOJ 4027】 4027: [HEOI2015]兔子与樱花 (贪心)
  • 原文地址:https://www.cnblogs.com/xiaoxiao95/p/16385417.html
Copyright © 2020-2023  润新知