如何避免接口重复请求(axios推荐使用AbortController)

前言:

我们日常开发中,经常会遇到点击一个按钮或者进行搜索时,请求接口的需求。

如果我们不做优化,连续点击按钮或者进行搜索,接口会重复请求。

以axios为例,我们一般以以下几种方法为主:

1.使用防抖、节流函数限制请求操作(老传统,但是已经不是最佳实践了)

2.自定义节流阀(比如自定义一个字段loading,请求前值是true,请求后改为false。如果为值true,就终止往下请求,体验感很不友好,因为我们搜索的时候,会经常更换文字,所以上一个请求没结束,下个就没法请求。不推荐)

javascript 复制代码
const getList = () => {
  if(loading.value) return
  loading.value = true
  axios.get('/user/12345')
    .then(res=> {
      loading.value = fasle
    })
}

3.使用axios请求库提供的api来解决重复请求的问题, AbortController或者CancelToken

Tips: 有些请求库已经内置了这一功能,比如alova.js,有些之前同事的公司已经在运用,听说效果很不错,也很轻便,不需要配置便能过滤重复请求。但是目前我们大部分公司还是以axios为主的,所以我们下面主要分享下在axios里怎么完成这一功能。( 对alova感兴趣的伙伴,可以移步至官网了解下Alova.JS - 轻量级请求策略库 | Alova.JS

AbortController

从v0.22.0开始,`Axios`支持`AbortController`以获取API的方式取消请求。具体如下:

javascript 复制代码
const controller = new AbortController();

axios.get('/foo/bar', {
   signal: controller.signal
}).then(function(response) {
   //...
});
// 取消请求
controller.abort()

示例:

javascript 复制代码
<template>
  <div>
    <button @click="fetchData">请求</button>
  </div>
</template>

<script setup>
import { ref } from 'vue';
import axios from 'axios';

let controller = null;


function fetchData() {
  if (controller) {
    controller.abort();
    controller = null;
  }
  controller = new AbortController();
  
  axios.get('https://api/user/12345',{signal: controller.signal})  //
    .then(response => {
      ...
    })
}

</script>

效果如下图:可以看到,重复的请求会直接被终止掉!

axios.CancelToken

deprecated

此 API 从 v0.22.0 开始已被弃用,不应在新项目中使用。

CancelToken官网示例

官网使用方法传送门:取消请求 | Axios中文文档 | Axios中文网

javascript 复制代码
const CancelToken = axios.CancelToken;
const source = CancelToken.source();

axios.get('/user/12345', {
  cancelToken: source.token
}).catch(function (thrown) {
  if (axios.isCancel(thrown)) {
    console.log('Request canceled', thrown.message);
  } else {
    // 处理错误
  }
});

axios.post('/user/12345', {
  name: 'new name'
}, {
  cancelToken: source.token
})

// 取消请求(message 参数是可选的)
source.cancel('Operation canceled by the user.');

示例:

javascript 复制代码
<template>
  <div>
    <button @click="fetchData">请求</button>
  </div>
</template>

<script setup>
import { ref } from 'vue';
import axios from 'axios';

let cancelTokenSource = null;


function fetchData() {
  if (cancelTokenSource) {
    cancelTokenSource.cancel('Operation canceled by the user.');
    cancelTokenSource = null;
  }
  cancelTokenSource = axios.CancelToken.source();
  
  axios.get('http://api/uesr/12345',{cancelToken: cancelTokenSource.token})  //
    .then(response => {
     ...
    })
}

</script>

兼容

注意: 可以使用同一个 cancel token 或 signal 取消多个请求。

在过渡期间,您可以使用这两种取消 API,即使是针对同一个请求

javascript 复制代码
const controller = new AbortController();

const CancelToken = axios.CancelToken;
const source = CancelToken.source();

axios.get('/user/12345', {
  cancelToken: source.token,
  signal: controller.signal
}).catch(function (thrown) {
  if (axios.isCancel(thrown)) {
    console.log('Request canceled', thrown.message);
  } else {
    // 处理错误
  }
});

axios.post('/user/12345', {
  name: 'new name'
}, {
  cancelToken: source.token
})

// 取消请求 (message 参数是可选的)
source.cancel('Operation canceled by the user.');
// 或
controller.abort(); // 不支持 message 参数
相关推荐
懒大王爱吃狼30 分钟前
Python教程:python枚举类定义和使用
开发语言·前端·javascript·python·python基础·python编程·python书籍
待磨的钝刨2 小时前
【格式化查看JSON文件】coco的json文件内容都在一行如何按照json格式查看
开发语言·javascript·json
逐·風4 小时前
unity关于自定义渲染、内存管理、性能调优、复杂物理模拟、并行计算以及插件开发
前端·unity·c#
Devil枫5 小时前
Vue 3 单元测试与E2E测试
前端·vue.js·单元测试
尚梦6 小时前
uni-app 封装刘海状态栏(适用小程序, h5, 头条小程序)
前端·小程序·uni-app
GIS程序媛—椰子6 小时前
【Vue 全家桶】6、vue-router 路由(更新中)
前端·vue.js
前端青山6 小时前
Node.js-增强 API 安全性和性能优化
开发语言·前端·javascript·性能优化·前端框架·node.js
毕业设计制作和分享7 小时前
ssm《数据库系统原理》课程平台的设计与实现+vue
前端·数据库·vue.js·oracle·mybatis
从兄8 小时前
vue 使用docx-preview 预览替换文档内的特定变量
javascript·vue.js·ecmascript
清灵xmf9 小时前
在 Vue 中实现与优化轮询技术
前端·javascript·vue·轮询