Frontend - 防止多次请求,避免重复请求

目录

一、避免重复执行的多种情况

(一)根据用途

(二)根据用户操作

二、具体实现

[(一)"Ajax "结合disabled (防止多次请求),避免多次点击重复请求](#(一)“Ajax ”结合disabled (防止多次请求),避免多次点击重复请求)

[1. 适用场景](#1. 适用场景)

[2. 解决办法](#2. 解决办法)

[3. 示例](#3. 示例)

[(二)unbind 和 bind(防止内存溢出),避免长按重复操作](#(二)unbind 和 bind(防止内存溢出),避免长按重复操作)

[1. 适用场景](#1. 适用场景)

[2. 解决办法](#2. 解决办法)

[3. 注意](#3. 注意)

[4. 示例](#4. 示例)

(1)普通写法,会出现问题:长按时,会多次执行弹出框动作

(2)进阶写法,解决长按时多次执行的问题

(3)针对click、keydown(与keyup同理)

[(三)setTimeout 防抖 ,避免多次重复操作](#(三)setTimeout 防抖 ,避免多次重复操作)

[(四)setTimeout 节流 ,避免多次重复操作](#(四)setTimeout 节流 ,避免多次重复操作)


一、避免重复执行的多种情况

(一)根据用途

  1. 针对按钮点击事件:设置disable属性(执行第一次的操作)、利用bind和unbind(执行最后一次的操作)、loading(执行最后一次的操作)。

  2. 针对输入框输入事件:防抖(执行最后一次的操作)

  3. 针对滚动事件:节流(执行第一次的操作)

(二)根据用户操作

  1. 针对无意识连续操作:利用bind和unbind、防抖、节流

  2. 针对故意连续操作:设置disable属性、loading(当数据全部更新好了再让用户操作)

二、具体实现

(一)"Ajax "结合disabled (防止多次请求),避免多次点击重复请求

1. 适用场景

同时执行多次相同操作。例如,短时间内执行多次点击事件,进行多个ajax请求。

2. 解决办法

在执行操作后,立马禁用操作按钮;在完成请求后,恢复按钮的可用状态。

3. 示例

javascript 复制代码
// 第一种
$('#id_ok').attr("disabled", true); // 禁用按钮,在"传递数据给后端"前(ajax里,放在beforeSend方法中)
$('#id_ok').attr("disabled", false); // 恢复按钮的可用状态,在 "前端渲染"后(ajax里,放在complete方法中)

// 第二种
$("#id_query_btn").attr({ disabled: "disabled" }); // 禁用按钮
$("#id_query_btn").removeAttr("disabled"); // 恢复按钮的可用状态

(二)unbind 和 bind(防止内存溢出),避免长按重复操作

1. 适用场景

在用户连续操作时,会重复请求多次。例如:点击时一直长按。

2. 解决办法

使用 unbind 和 bind,在用户连续操作时,只请求最后一次操作,前面重复的操作被 unbind 释放掉。

3. 注意

只是避免连续操作,但没有避免短时间内频繁操作。例如:点击时,只是避免了"长按",但不能避免同时多次点击。

4. 示例

(1)普通写法,会出现问题:长按时,会多次执行弹出框动作

即,当一直长按时,keyup事件被多次绑定,执行多次事件。

javascript 复制代码
$(document).keyup.(function(event){
    alert(event.which); //显示按键对应的数字编号
})
(2)进阶写法,解决长按时多次执行的问题

即,绑定keyup事件前,先解绑。

javascript 复制代码
$("#id_ok").unbind("keyup").bind("keyup", function(event){
   if (event.keyCode == 13) {
      alert(event.keyCode);
   }
})
(3)针对click、keydown(与keyup同理)
javascript 复制代码
$("#id_ok").unbind('click').bind('click', function () { } );

(三)setTimeout 防抖 ,避免多次重复操作

javascript 复制代码
// 第一种 JavaScript的addEventListener
document.getElementById("id_ok").addEventListener("click", fn_debounce(excute_data, 1000));
// 第二种 jQuery的on()方法
$('#id_ok').on('click', fn_debounce(excute_data, 1000));
// 需执行的事件
function excute_data() {alert("测试"); }
/** 
 * 防抖:某个时间期限(500毫秒)内,事件只执行一次。
 * @fn [function] 需要防抖的函数
 * @timeint [number] 毫秒,防抖期限
*/
function fn_debounce(fn, timeint) {
    let timeout; // 闭包,在定时方法作用域外部。会保留在返回的函数的闭包中,即保留上一次事件的处理状态,直到定时器完成执行。
    return function (e) {
        clearTimeout(timeout);// 清除上一次执行保留的timeout计时器
        timeout = setTimeout(() => {fn.apply(this, arguments);}, timeint ? timeint : 500); // 对该事件何时执行,重新设定计时器
    };
}

(四)setTimeout 节流 ,避免多次重复操作

javascript 复制代码
// 第一种 JavaScript的addEventListener
document.getElementById("id_ok").addEventListener("click", fn_throttle(excute_data, 1000));
// 第二种 jQuery的on()方法
$('#id_ok').on('click', fn_throttle(excute_data, 1000));
// 需执行的事件
function excute_data() {alert("测试"); }
/** 
 * 节流:某个时间期限(500毫秒)内,事件只执行一次。
 * @fn [function] 需要节流的函数
 * @timeint [number] 毫秒,节流期限
*/
function fn_throttle(fn, timeint) {
    let can_run=true; // 闭包,在定时方法作用域外部。会保留在返回的函数的闭包中,即保留上一次事件的处理状态,直到定时器完成执行。
    return function (e) {
        if(can_run){ // 用can_run变量控制是否执行fn函数
            fn.apply(this, arguments);
            can_run=false; 
            setTimeout(() => {can_run=true;}, timeint ? timeint : 500);
        }
    };
}
相关推荐
zhanghaha131421 分钟前
HTML系列教程:14_HTML 表单与输入框 <form>、<input> 零基础详解
java·前端·javascript
李少兄6 小时前
JavaScript 数据类型完全指南
开发语言·javascript·ecmascript
shmily麻瓜小菜鸡10 小时前
JS/TS 易踩坑知识点 — 模块化与工程化类
开发语言·javascript·ecmascript
默_笙12 小时前
🍕 AI 的嘴巴装了水管(上):从"等它说完"到"边说边听"的流式输出指南
前端·javascript
暖焰核心12 小时前
继承全解——继承、默认成员函数、切片、隐藏与虚继承
java·前端·javascript
艾伦野鸽ggg13 小时前
前端异步请求的状态竞争(请求竞态)问题
前端·javascript·axios
是立不是利13 小时前
前端交互基石:深入剖析JavaScript三级联动背后的设计哲学
开发语言·前端·javascript
老刘的望远镜13 小时前
AgentScope Java 从零(03):Agent 的记性默认全开,我在第 50 轮翻了车
java·开发语言·javascript
前端精髓13 小时前
React 更新 state 中的对象
javascript·react.js·ecmascript
可乐鸡翅yeah_14 小时前
hls.js 播放质量埋点实战,采集卡顿、起播、错误指标定位线上用户问题
开发语言·前端·javascript·ecmascript·音视频·m3u8·音视频在线播放