< 今日小技巧:Axios封装,接口请求增加防抖功能 >

news2024/12/21 21:59:03

在这里插入图片描述

文章目录

  • 👉 前言
  • 👉 一、核心代码 : 防抖函数
  • 👉 二、Axios封装中的配置
  • 👉 三、实现原理
  • 👉 结论
  • 👉 补充优化: 解决多个接口请求,拦截掉了需要的请求
    • > 防抖函数
    • > 引用位置
  • 往期内容 💨


👉 前言

防抖节流概念: < 性能优化:认识防抖与节流,如何实现呢?它们又有何区别? >

今天这篇文章,主要是讲述对axios封装的请求,由于部分请求可能存在延时的情况。使得接口可能存在会被持续点击(即:接口未响应的时间内,被持续请求),导致重复请求的问题,容易降低前后端服务的性能!

故提出给axios封装的配置里面,新增一个防抖函数,用来限制全局请求的防抖。不过介于部分接口可能存在需要持续请求的情况,所以增加一个参数来判断是否启用防抖函数

👉 一、核心代码 : 防抖函数

const debounce = (fn, delay, immediate = true) => {
  // 1.定义一个定时器, 保存上一次的定时器

  let timeout = JSON.parse(localStorage.getItem('timeout')) || null
  // window.console.log(fn, delay, timeout)
  // 2.真正执行的函数
  const _debounce = function() {
    let context = this;
    let args = arguments;

    if (timeout) clearTimeout(timeout); // timeout 不为null
    if (immediate) {
      // 第一次会立即执行,以后只有事件执行后才会再次触发
      let callNow = !timeout;
      timeout = setTimeout(function() {
        timeout = null;
      }, delay)
      if (callNow) {
        fn.apply(context, args)
      }
    } else {
      timeout = setTimeout(function() {
        fn.apply(context, args)
      }, delay);
    }
    localStorage.setItem('timeout', timeout)
  }

  // 封装取消功能
  _debounce.cancel = function() {
    if (timeout) clearTimeout(timeout)
    timeout = null
    localStorage.setItem('timeout', null)
  }

  return _debounce
}

export default debounce;

👉 二、Axios封装中的配置

// 使用axios请求
this.xxxName({
  ...
  isDebounce: true // 入参
})
  .then((res) => {
    ...
  })
  .finally(() => {});

---------------------------------------------------

import debounce from "./debounce.js";

export default function(options) {
  // options 为接口入参配置,options.data为接口参数
  ...
  let isDebounce = false;
  
  try{
    isDebounce = config.data.isDebounce;
    if(isDebounce) {
      delete data.isDebounce;
    }
  } catch(e){
    //TODO handle the exception
    isDebounce = false
  }
  
  return createPromise(type, url, data, config, socket, cache, isDebounce);
}

function createPromise(type, url, data, config, socket, cache = {}, isDebounce = false) {
  ...

  return new Promise(function(resolve, reject) {
    if (cacheData) {
      resolve(cacheData);
    } else {
      const fn = () => {
        // 请求接口代码
        http
          .then(function(res) {
            ...
          })
          .catch(function(res) {
            ...
            reject(res);
          })
          .finally(() => {
            debounce().cancel()
          });
      }
      
      // 对axios请求进行防抖配置, 防抖时间为 5s
      if(isDebounce) {
        debounce(fn, 5000)()
      } else {
        fn()
      }
    }
  });
}

👉 三、实现原理

介于我们封装axios后,每次请求都会统一执行一次我们封装的函数。从而统一在函数内进行防抖判断,防止短时间发出大量误触请求!

因为小温是在项目后期进行功能优化,所以以入参的形式(默认关闭)控制是否开启防抖功能!

难点:由于防抖函数位于axios封装方法中,所以每次请求都无法获取到上次执行遗留下来的timer。相当于每次执行的防抖函数都为新的函数,导致timer变量无法被闭包存储,无法起到请求防抖的功能! 故而通过将timer暂存至本地,解决问题!

给防抖函数增加中断防抖的功能,在请求响应后通过cancel函数关闭当前防抖流程!

👉 结论

本篇文章仅是基于实际开发中,对防抖概念的实际应用。可能部分逻辑存在问题,需要各位小伙伴在使用时,根据实际场景做修改! 本文仅用于思路指导!在实际运用还是存在问题: 比如当存在两个及以上接口同时请求时,会使防抖函数失效,导致后请求的接口被强行取消。

这个问题也需要重点去解决! 但是本项目中,仅用于列表接口查询时的防抖,故暂不解决这个问题!

原因: 出现问题的原因也很简单, 由于 timer 只存一个参数,防抖函数无法准确的判断防抖对象, 就是同时请求的接口,后面的接口被当作第一个触发的请求接口的抖动请求(也就是防抖防错对象了),故被防抖阻止了。

解决思路: 将本地存储的数据,存储为object类型, 按接口地址 Url 作为 key值存储 timer,请求之前,查询当前 Url,在本地存储中查询有没有正在执行的请求!若有,则进入防抖。反之,则执行正常请求流程!

👉 补充优化: 解决多个接口请求,拦截掉了需要的请求

> 防抖函数

const debounce = (fn, delay, url = '', immediate = true) => {
  // 1.定义一个定时器, 保存上一次的定时器

  let timeout = JSON.parse(localStorage.getItem(url)) || null
  // window.console.log(url, timeout)
  // 2.真正执行的函数
  const _debounce = function() {
    let context = this;
    let args = arguments;

    if (timeout) clearTimeout(timeout); // timeout 不为null
    ... 中间内容不变
    localStorage.setItem(url, timeout)
  }

  // 封装取消功能
  _debounce.cancel = function() {
    let timeout_cancel = JSON.parse(localStorage.getItem(url)) || null
    if (timeout_cancel) clearTimeout(timeout_cancel)
    timeout = null
    localStorage.removeItem(url)
  }

  return _debounce
}

export default debounce;

> 引用位置

新增入参 Url ,请求地址,如果怕接口信息被网站获取,导致泄漏! 可以以斜杠为分割字符串,使用sqit('/')分割! 取最后一个作为本地存储的标记(key)值

效果图

最后的最后,如果觉得小温这篇文章对你有所帮助,请不要吝惜你的小手,给小温三连支持一下吧~ 😘

往期内容 💨

🔥 < 每日算法 - JavaScript解析:跳跃游戏 Ⅰ/ Ⅱ - 贪心 >

🔥 < 每日算法 - JavaScript解析:一文解决 “ 买卖股票 ” 系列算法题 >

🔥 < vue + ElementUi 组件封装:实现弹窗展示富文本数据,允许全文搜索高亮显示搜索内容 >

🔥 < 每日算法:一文带你认识 “ 双指针算法 ” >

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/788494.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

c 学习笔记(自用)---GCC编译器

1.GCC编译器的使用 1) 一个c文件预处理和编译的过程 可以用以上命令去逐步调试下,看看预处理的过程 2)命令举例与解释 #源文件较少的情况下 gcc -o test main.c sub.c #分别将 main.c 和sub.c文件进行预处理、编译、汇编, #…

push_back 和 emplace_back 的区别

文章目录 1、vector::push_back1.1 void push_back(T&& x) ; (C11)参数返回值类型大小 和 容量移动左值用户自定义类型使用 push_back 1.2 void push_back(const T &x);参数返回值类型 1.3 如果 vector 的 size 超过当前capacity,push_back 会使迭代器、…

一分钟学一个 Linux 命令 - rm

前言 大家好,我是 god23bin,欢迎回到咱们的《一分钟学一个 Linux 命令》系列,今天我要讲的是一个比较危险的命令,rm 命令,没错,你可以没听过 rm 命令,但是删库跑路你不可能没听过吧&#xff1f…

RISCV -3 RV32I/RV64I基本整型指令集

RISCV -3 RV32I/RV64I基本整型指令集 1 RV32I Base Integer Instruction Set1.1 Programmers’ Model for Base Integer ISA1.2 Base Instruction Formats1.3 Immediate Encoding Variants1.4 Integer Computational Instructions1.4.1 Integer Register-Immediate Instruction…

25-30天每日强训选择题改错解析

int i5; int s(i)(i)(i–)(–i); s( )//s 的值是什么? A 28 B 25 C 21 D 26 E 24 F 23 正确答案: E 5775 24 或者 --在后先不变化数值 -- 在前先变化再运算 以下哪项不属于java类加载过程? A 生成java.lang.Class对象 B int类型对象成…

【Vue】day04-组件通信

day04 一、学习目标 1.组件的三大组成部分(结构/样式/逻辑) scoped解决样式冲突/data是一个函数 2.组件通信 组件通信语法 父传子 子传父 非父子通信(扩展) 3.综合案例:小黑记事本(组件版&#xf…

Windows下达梦数据库图形化安装、初始化数据库及连接

文章目录 前言一、达梦数据库安装1、下载安装包2、解压3、安装 二、初始化数据库三、连接数据库1、客户端工具2、输入连接信息3、成功连接 总结 前言 本节将介绍达梦数据库的图形化界面安装的细节,本节以Win11系统及DM8为基础进行讲解,虽然是图形化安装…

5. Bean 的作用域和生命周期

目录 1. Bean 被修改的案例 2. 作用域定义 2.1 Bean 的 6 种作用域 singleton prototype request session application(了解) websocket (了解) 单例作用域(singleton)VS 全局作用域(…

企业知识管理系统安全是重中之重

企业开展知识管理工作的益处是全方位的,效果能从业务的各方面得到体现,最终效果就是企业竞争力的提升与企业经营业绩的提升。 知识管理系统的意义在于,构建系统的知识库,对纷杂的知识内容(方案、策划、制度等&#xf…

【业务功能篇51】对象复制的三种方式 工具类Orika、反射、BeanUtils浅拷贝

业务场景&#xff1a; 设计规范前提下&#xff0c;我们数据层传输承载的是用DTO&#xff0c;而到控制层返回给前端会对应定义一个VO对象&#xff0c;比如是一个问题单数据集合list<DTO>,数据层接收的是DTO对对象&#xff0c;到控制层接收后需要转换成list<VO>,这里…

项目中如何使用文件IO?【大学学了好几门语言都有IO,到底怎么用?】

import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException;public class TestFile {public static void main(String[] args) throws IOException {// 通过这个简单的程序, 把一个文件的内容读取出…

Docker Compose 容器编排

Docker compose Docker compose 实现单机容器集群编排管理&#xff08;使用一个模板文件定义多个应用容器的启动参数和依赖关系&#xff0c;并使用docker compose来根据这个模板文件的配置来启动容器&#xff09; 通俗来说就是把之前的多条docker run启动容器命令 转换为docker…

关于云服务器ECS、宝塔的安装配置以及图床的使用

一、阿里云服务器的申请以及宝塔的安装 安装配置服务器的原理&#xff1a; step1&#xff1a;地址栏输入阿里云服务器官网地址 step2&#xff1a;在首页依次点击以下内容&#xff1a; step3&#xff1a;选择立即购买&#xff0c;并填写以下内容&#xff1a; step4&#xff1a…

6.运算符

6.1赋值运算符 ➢已经学过的赋值运算符&#xff1a; ➢其他赋值运算符&#xff1a; 、-、*、/、% 6.2 一元运算符 众多的JavaScript的运算符可以根据所需表达式的个数, 分为一元运算符、二元运算符、三元运算符 ●二元运算符: 例&#xff1a;let num1020 ●一元运算符: 例…

Vue3输入框(Input)

APIs 参数说明类型默认值必传width输入框宽度string | number‘100%’falseaddonBefore设置前置标签string | slot‘’falseaddonAfter设置后置标签string | slot‘’falseallowClear可以点击清除图标删除内容booleanfalsefalsepassword是否启用密码框booleanfalsefalsedisabl…

CSS3 Flexbox

Flex 是 Flexible Box 的缩写&#xff0c;意为弹性盒子布局。 CSS3中一种新的布局模式&#xff1a;W3C在2009年提出的一种布局方案&#xff0c;一种当页面需要适应不同的屏幕大小以及设备类型时确保元素拥有恰当的行为的布局方式。其目的是提供一种更加有效的方式来对一个容器…

回收站不见了?正确的2个操作方法!

大家有没有遇到回收站不见了的情况啊&#xff1f;真的很崩溃&#xff0c;我误删了一个比较重要的文件&#xff0c;想在回收站中把它还原&#xff0c;才发现我的回收站不见了&#xff01;这可咋整啊&#xff1f; 回收站是电脑操作系统中一个比较重要的功能&#xff0c;它可以帮助…

Ceph简介和特性

Ceph是一个多版本存储系统&#xff0c;它把每一个待管理的数据流(例如一个文件) 切分为一到多个固定大小的对象数据&#xff0c;并以其为原子单元完成数据存取。 对象数据的底层存储服务是由多个主机 (host) 组成的存储集群&#xff0c;该集群也被称之为 RADOS (ReliableAutoma…

DS18B20的原理及实例代码(51单片机、STM32单片机)

一、DS18B20介绍 DS18B20数字温度传感器是DALLAS公司生产的单总线器件&#xff0c;用它来组成一个测温系统具有线路简单&#xff0c;体积小&#xff0c;在一根通信线上可以挂很多这样的数字温度传感器&#xff0c;十分方便。 温度传感器种类众多&#xff0c;应用在高精度、高可…

快排、二路归并疑难杂症

蒟蒻小♥复习机试&#xff0c;记录一些疑点和注意点。 细节见代码注释 快排 快排中的边界条件判断需保证i<j&#xff0c;即满足label基准左边的数均小于右边的数。<的判断可能让子问题求解陷入死循环。 #include <iostream> #include <stdio.h> #include …