登录失效后,出现多个请求失败的土司提示/切换路由时,取消上一个页

2020-05-11  本文已影响0人  前端青音

【问题】:

登录超时后,自动跳到登录页,出现多个请求失败的土司提示

【原因】:

点击页面发送请求,当后端检测到登录失效后,会返回特定的状态码,出现请求超时的提示,前端拦截对应的状态码,登出跳到登录页。点击页面发送请求时,可能会同时发起多个请求,导致的。

【解决方案】:

当切换路由时,取消上一个页面的所有请求。

代码:

在axios封装页面中,添加一个变量axiosPromiseArr存放cancel方法,当切换路由的时候,调用。
axios.js

import axios from 'axios'
import qs from 'qs'
import store from '@/store'
import router from '@/router'

// import { Message } from 'element-ui'
import { host } from '@/__conf'
let axiosPromiseArr = []

const httpRequest = axios.create({
  baseURL: process.env.NODE_ENV === 'production' ? host : '',
  timeout: 60000
})

// 请求拦截
httpRequest.interceptors.request.use(
  function (config) {
    config.cancelToken = new axios.CancelToken(cancel => {
      axiosPromiseArr.push({ cancel })
    })
    // token
    if (store.state.token) {
      config.headers['Authorization'] = store.state.token
    }
    if (
      config.method === 'post' &&
      config.data &&
      config.headers['Content-Type'] !== 'application/json' &&
      config.headers['Content-Type'] !== 'multipart/form-data'
    ) {
      config.data = qs.stringify(config.data)
    }
    return config
  },
  function (error) {
    return Promise.reject(error)
  }
)

// 响应拦截
httpRequest.interceptors.response.use(
  function (response) {
    let code = response.data.code
    let whiteList = [0, 200]
    if (whiteList.includes(code)) {
      return response.data
    }
    // 跳转到登录页面
    if (
      [
        10005,
        500000,
        500001,
        500002,
        500003,
        500004,
        600000,
        600001,
        150000,
        100001,
        20003
      ].includes(code)
    ) {
      store.commit('logout')
      router.push('/login')
    }
    // Message({ type: 'error', message: response.data.msg })
    return Promise.reject(response.data)
  },
  function (error) {
    // Message({ type: 'error', message: 'hhhhhhh' })
    if (error && error.message) {
      if (error.message === 'timeout of 10000ms exceeded') {
        return Promise.reject(error)
      }
      return new Promise(() => { })
    }
    console.log(error)
    return Promise.reject(error)
  }
)

export { httpRequest, axiosPromiseArr }

在main.js中,路由前置守卫中遍历取消所有请求
main.js

import { axiosPromiseArr } from '@/lib/axios'
router.beforeEach((to, from, next) => {
  // title
  axiosPromiseArr.forEach((ele, index) => {
    ele.cancel('我中断一个请求康康')
    delete axiosPromiseArr[index]
  }) 
  next()
})

【总结】:

将发起的所有请求,都存于axiosPromiseArr,并且给其挂载cancel方法。切换路由时会触发router.beforeEach 路由前置守卫,在该路由钩子函数中,调用所有请求的cancel方法,取消请求。

上一篇下一篇

猜你喜欢

热点阅读