美文网首页
axios 1.3.x 以上版本,中断请求

axios 1.3.x 以上版本,中断请求

作者: 冰落寞成 | 来源:发表于2024-03-14 09:22 被阅读0次

AbortController

AbortController 接口表示一个控制器对象,允许你根据需要中止一个或多个 Web 请求。

你可以使用 AbortController.AbortController() 构造函数创建一个新的 AbortController。使用 AbortSignal 对象可以完成与 DOM 请求的通信。

示例

发送请求

export const getConsumableByPage = (data,config) => get('/Consumable/findByPage', data,config) // 获取列表
const getList = () => {

   controller = new AbortController();
   const signal = controller.signal;
    getConsumableByPage(searchParams, { signal }).then(res => {
    loading.close()
    if (res.code === 200) {
      tableOptions.list = res.data?.content
      searchParams.total = res.data?.totalElements
    }
  }).catch(err => {
    console.log(err)
    loading.close()
  })
}

中断请求

const terminateRequest= ()=>{
   if (controller) {
     controller.abort();
    console.log("中止请求");
   }
 }

request 封装

1、定义变量

const {isCancel} = axios
const cacheRequest = {}

2 定义终止函数

/**
 * 终止请求
 * @param {*} resKey 
 */
const removeCacheRequest=(resKey)=>{
  if(cacheRequest[resKey]){
    cacheRequest[resKey].abort();
    delete cacheRequest[resKey]
  }
}

3、请求拦截器里处理终止请求操作

request.interceptors.request.use(
  config => {
    const {url,method,removeCache=false} = config
    if(removeCache){// 终止请求
      removeCacheRequest(`${url}&${method}`)// 如果请求函数里传了需要清除重复请求的removeCache,并且这个重复请求存在,删除之前的请求
      const controller = new AbortController();
      config.signal  = controller.signal;
      cacheRequest[`${url}&${method}`] = controller
    }
    return config
  },
  error => {
    return Promise.reject(error)
  }
)

4、在响应拦截器里处理终止请求

request.interceptors.response.use(
  response => {
    // 请求成功,从队列里删除该controller
    const {url,method,removeCache=false} = response.config
    if(removeCache)  removeCacheRequest(`${url}&${method}`)
  },
  error => {
    let code = 0
    try {
      code = error.response.data.status
    } catch (e) {
    }
    if(isCancel(error)){
      return Promise.reject({
        msg:'重复请求,自动拦截并取消'
      })
    }else{
      return Promise.reject(error)
    }
  }
)

5、应用举例

export const getConsumableByPage = (data) => get('/Consumable/findByPage', data,{removeCache:true})

request 封装全代码

import axios from 'axios'
import { apiPath, loginInterception } from '@/config' // 线上服务
const {isCancel} = axios
const cacheRequest = {}
// import store from '@/store'
import router from '@/router'
import { pinia, userStore } from '@/store'
import { ElMessage } from 'element-plus'
const store = userStore(pinia)
/**
 * 终止请求
 * @param {*} resKey 
 */
const removeCacheRequest=(resKey)=>{
  if(cacheRequest[resKey]){
    cacheRequest[resKey].abort();
    delete cacheRequest[resKey]
  }
}
const request = axios.create({
  baseURL: apiPath,
  timeout: 50 * 1000
})
request.interceptors.request.use(
  config => {
    // console.log(store)
    const {url,method,removeCache=false} = config
    console.log('请求拦截器',url,method,removeCache)

    const token = store.token
    const tenantId = store.tenant_id
    if (token) {
      config.headers.token = token
    }
    if (tenantId) {
      config.headers['x-tenant-id'] = tenantId
    }
    if(removeCache){// 终止请求
      removeCacheRequest(`${url}&${method}`)// 如果请求函数里传了需要清除重复请求的removeCache,并且这个重复请求存在,删除之前的请求
      const controller = new AbortController();
      config.signal  = controller.signal;
      cacheRequest[`${url}&${method}`] = controller
    }
    return config
  },
  error => {
    return Promise.reject(error)
  }
)

request.interceptors.response.use(
  response => {
    // 请求成功,从队列里删除该controller
    const {url,method,removeCache=false} = response.config
    if(removeCache)  removeCacheRequest(`${url}&${method}`)
    let res
    if (response.config.downBlob) { // 下载文件
      const json = {
        blob: response.data,
        headers: response.headers
      }
      res = json
    } else {
      res = response.data
    }
    const path = router.currentRoute.path
    if (res.code === 100) { // 代表登录失效
      if (loginInterception) {
        store.clearUserStore()
        const messageDom = document.getElementsByClassName('el-message')[0]
        if (messageDom === undefined) {
          ElMessage({
            type: 'error',
            message: '未登录或者登录失效,请重新登录',
            onClose: () => {
              if (path !== '/login') { // 在login 页就不要跳转了
                router.push('/login')
              }
            }
          })
        }
      }
    }
    return res
  },
  error => {
    let code = 0
    try {
      code = error.response.data.status
    } catch (e) {
    }
    if(isCancel(error)){
      return Promise.reject({
        msg:'重复请求,自动拦截并取消'
      })
    }else{
      return Promise.reject(error)
    }
    
  }
)
/**
 * @description: get请求
 * @param {string} url 请求地址后缀
 * @param {object} params 请求参数
 * @param {object} config 请求配置
 * @return {*}
 */
const get = (url, params, config) => {
  const reqData = {
    method: 'get',
    url: url,
    params
  }
  if (config) {
    Object.assign(reqData, config)
  }
  return request(reqData)
}

/**
 * @description: post请求
 * @param {string} url 请求地址后缀
 * @param {object} params 请求参数
 * @param {object} config 请求配置
 * @return {*}
 */
const post = (url, data, config) => {
  const reqData = {
    method: 'post',
    url: url,
    data
  }
  if (config) {
    Object.assign(reqData, config)
  }
  return request(reqData)
}
/**
 * @description: post请求
 * @param {string} url 请求地址后缀
 * @param {object} data 请求参数
 * @param {object} params 请求参数
 * @param {object} config 请求配置
 * @return {*}
 */
const postAndGet = (url, data, params, config) => {
  console.log(data, params)
  const reqData = {
    method: 'post',
    url: url,
    data,
    params
  }
  if (config) {
    Object.assign(reqData, config)
  }
  return request(reqData)
}
/**
 * @description: post请求(参数拼接式,类get)
 * @param {string} url 请求地址后缀
 * @param {object} params 请求参数
 * @param {object} config 请求配置
 * @return {*}
 */
const postOfGet = (url, params, config) => {
  const reqData = {
    method: 'post',
    url: url,
    params
  }
  if (config) {
    Object.assign(reqData, config)
  }
  return request(reqData)
}
/**
 * @description: formData对象+get拼接式复合请求
 * @param {*} url 请求地址后缀
 * @param {*} formData 请求数据
 * @param {*} config
 * @param {*} config.params 拼接数据
 * @return {*}
 */
const postOfForm = (url, formData, config) => {
  const reqData = {
    method: 'post',
    url: url,
    data: formData,
    headers: { 'Content-Type': 'multipart/form-data' }
  }
  if (config) {
    Object.assign(reqData, config)
  }
  return request(reqData)
}
export { request, get, post, postOfGet, postOfForm, postAndGet }

相关文章

网友评论

      本文标题:axios 1.3.x 以上版本,中断请求

      本文链接:https://www.haomeiwen.com/subject/vdwbzdtx.html