防重复提交

1. Debouncing(防抖)

原理

  • 防抖是在一段时间内只执行最后一次请求。如果用户在设定时间内多次触发操作,只有最后一次操作会被执行,前面的操作会被取消。

优点

  • 避免短时间内重复请求,只执行最后一次操作。
  • 对用户频繁操作(如输入搜索关键字)非常有效。

缺点

  • 如果用户需要立即得到反馈,可能会产生延迟,因为必须等待设定的防抖时间过去才会发起请求。
  • 适合输入类场景,但不适合所有场景,比如按钮点击的请求场景。
js 复制代码
function debounce(fn, delay) {
  let timeout;
  return function (...args) {
    clearTimeout(timeout);
    timeout = setTimeout(() => fn.apply(this, args), delay);
  };
}

// 使用示例
const submitForm = debounce(function() {
  // 网络请求逻辑
}, 500);

2. Throttling(节流)

原理

  • 节流是在规定的时间间隔内只允许发起一次请求。无论用户在这段时间内多次触发操作,都只有一次操作会被执行,后续操作会被忽略。

优点

  • 能有效控制请求频率,避免过度请求。
  • 对于需要控制请求频率的场景(如滚动加载)非常适合。

缺点

  • 用户频繁操作时,某些操作可能被忽略,无法立即响应用户的每次操作。
  • 不适用于要求立即响应用户每次操作的场景。
js 复制代码
function throttle(fn, interval) {
  let lastTime = 0;
  return function (...args) {
    const now = Date.now();
    if (now - lastTime >= interval) {
      lastTime = now;
      fn.apply(this, args);
    }
  };
}

// 使用示例
const submitForm = throttle(function() {
  // 网络请求逻辑
}, 1000);

3. Loading 状态限制

原理

  • 利用 loading 状态变量在请求发起时设置为 true,请求完成后重置为 false。当 loadingtrue 时,阻止后续请求。

优点

  • 简单易实现,适用于需要确保单次操作期间不会重复触发请求的场景。
  • 用户点击操作后会立即得到反馈,提升用户体验。

缺点

  • 只适用于阻止在请求未完成之前的重复请求,不能限制在短时间内连续发起多次不同请求。
js 复制代码
data() {
  return {
    loading: false,
  };
},
methods: {
  submitForm() {
    if (this.loading) return;
    this.loading = true;

    uni.request({
      url: 'https://example.com/api/submit',
      method: 'POST',
      data: {},
    }).then(response => {
      // 处理响应
    }).finally(() => {
      this.loading = false;
    });
  }
}

总结

  • Debouncing 适合用户输入类操作,防止频繁请求,只执行最后一次操作。
  • Throttling 适合需要限制操作频率的场景,能有效控制请求频率。
  • Loading 状态限制 适合需要确保在请求完成前不会重复请求的场景,简单易用
js 复制代码
// //防抖
function debounce(fn, date) {
  let timer  //声明接收定时器的变量
  return function (...arg) {  // 获取参数
    timer && clearTimeout(timer)  // 清空定时器
    timer = setTimeout(() => {  //  生成新的定时器
      //因为箭头函数里的this指向上层作用域的this,所以这里可以直接用this,不需要声明其他的变量来接收
      fn.apply(this, arg) // fn()
    }, date)
  }
}
//--------------------------------
// 节流
function debounce(fn, data) {
  let timer = +new Date()  // 声明初始时间
  return function (...arg) { // 获取参数
    let newTimer = +new Date()  // 获取触发事件的时间
    if (newTimer - timer >= data) {  // 时间判断,是否满足条件
      fn.apply(this, arg)  // 调用需要执行的函数,修改this值,并且传入参数
      timer = +new Date() // 重置初始时间
    }
  }
}

// 状态锁
lock: false, // 防止多次点击

if (!this.lock) {
    this.lock = true
    uni.navigateTo({
        url: '/qualityInspection/pages/areaDetails/index',
        success: () => {
            this.lock = false;
        },
        fail: () => {
            this.lock = false;
        }
    })
}

// uniapp button loading
<button type="default" @click="payment" :loading="loading" :disabled="disabled">立即支付</button>

// 执行支付
async payment() {
    let params = {
        oderType: "order",
        openId: this.openId,
        platform: this.platform,
        pay_type: this.pay_type,
        orderId: this.id
    }
    uni.showLoading({
        title: '请稍等'
    })
    this.loading = true
    this.disabled = true
    let res = await orderPay(params);
    uni.hideLoading()
    this.loading = false
    this.disabled = false
},
相关推荐
To_OC3 小时前
LC 128 最长连续序列:别上来就排序,O (n) 解法才是这题的灵魂
javascript·算法·leetcode
kyriewen7 小时前
我用 50 行代码重写了 React Router 核心,终于搞懂了前端路由原理
前端·javascript·react.js
Asize9 小时前
HTML5 Canvas 基础:从按帧动画到 ECharts 数据可视化
前端·javascript·canvas
默_笙10 小时前
🎄 后端给我一堆扁平数据,我 10 行代码把它变成了树
前端·javascript
前端Hardy10 小时前
又一个 AI 神器火了!
前端·javascript·后端
锋行天下10 小时前
我试图优化 Vite 的拆包,结果首屏慢了 10 倍
前端·vue.js·架构
PBitW10 小时前
GPT训练我的第二天,我表示不过如此!!!😕😕😕
前端·javascript·面试
kyriewen11 小时前
白宫直接给 OpenAI 下了限制令,GPT-5.6 不能随便放出来了
前端·javascript·面试
ZhengEnCi15 小时前
Q02-Vue-React-index.html完全指南
vue.js·react.js·html
晴虹16 小时前
vue3-scroll-more:横向滚动条-元素或页签过多滚动显示处理的组件
前端·vue.js