axios的cancelToken封装


cancelToken

cancelToken简介

cancelToken是axios用来取请求的api

针对菜单的路由页面跳转,我们可以取消请求跳转前的请求,以提升页面性能减少不必要的等待。

AbortController简介

axios中,新增AbortController,将CancelToken标记为**deprecated**

  • MDN中介绍AbortController

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

    你可以使用 [AbortController.AbortController()](https://developer.mozilla.org/zh-CN/docs/Web/API/AbortController/AbortController) 构造函数创建一个新的 AbortController。使用 [AbortSignal](https://developer.mozilla.org/zh-CN/docs/Web/API/AbortSignal) 对象可以完成与 DOM 请求的通信。

image.png

实现axios的CancelToken

api.js

import axios from "axios";
const CancelToken = axios.CancelToken;
const sourceList = []

const opt = {
  //拓展默认属性
  //baseURL、cache、contentType、timeout等
  timeout: 80000, //统一设置超时时间
}

let instance = axios.create(opt);

function handleCancelToken(CancelToken, sourceList) {
  if(!CancelToken){
    return
  } 
  return {
    source: function source() {
      const source = CancelToken.source();
      sourceList.push(source)
      return {
        token: source?.token,
        cancel: function cancel(message){
          if(source?.canceled){
            return;
          }
          const index = sourceList?.findIndex(function (s) {
            return s === source
          })
          index !== -1 && source?.splice(index, 1)
          source?.cancel(message)
        }
      }
    }
  }
}

instance.interceptors.request.use(config => {
  //模拟封装配置项目

	//针对每一个请求添加一个CancelToken,在handleCancelToken内部记录请求的source
  const defaultParams = Object.assign(config, {
    cancelToken: handleCancelToken(CancelToken, sourceList)?.source()?.token
  })
  console.log(defaultParams, 'config')
  return defaultParams
}, err => {
  console.log(err, '请求错误')
})

instance.interceptors.response.use(res => {
  console.log(res, '响应结果')
  return res
}, err => {
  //TODO:错误码处理、Canceloken错误处理
  console.log(err, '响应错误')
  if(err?.message === '"myCanceledError"'){
    return
  }
})

//手动取消请求 -> 路由切换后取消请求
instance.abortAll = function(message){
  //**注意:第一个请求没有被取消**
  sourceList?.forEach( source => {
    source.canceled = true
    source.cancel(message)
  })
  sourceList.length = 0
}

export default instance;

测试文件:test.tsx

import api from './api'

export default function Index() {
  const send = () => {
    //let controller = new AbortController();
    //const signal = controller.signal;
    api({
      url: 'https://mdn.github.io/dom-examples/abort-api/sintel.mp4',
      method: 'get',
      params: {
        //signal: signal
      }
   })
  }

  const cancel= () => {
    //取消请求
    api?.abortAll('myCanceledError')
  }
  return (
    <div>
      <button onClick={send}>
        点击请求
      </button>
      <button onClick={cancel}>
        取消请求
      </button>
    </div>
  )
}

Prompt → ‘react-router-dom’

const promptCallback = () => {
		//todo
		api?.abortAll('myCanceledError')
}

<Prompt when={true} message={promptCallback} />

AbortController同理

controller = new AbortController();


文章作者: echo_sixi
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 echo_sixi !
  目录