防重复提交

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
},
相关推荐
Jinkxs10 小时前
JavaScript性能优化实战技术
开发语言·javascript·性能优化
TE-茶叶蛋11 小时前
Flutter、Vue 3 和 React 在 UI 布局比较
vue.js·flutter·react.js
Maybyy11 小时前
力扣242.有效的字母异位词
java·javascript·leetcode
小彭努力中11 小时前
147.在 Vue3 中使用 OpenLayers 地图上 ECharts 模拟飞机循环飞行
前端·javascript·vue.js·ecmascript·echarts
老马聊技术11 小时前
日历插件-FullCalendar的详细使用
前端·javascript
zhu_zhu_xia11 小时前
cesium添加原生MVT矢量瓦片方案
javascript·arcgis·webgl·cesium
咔咔一顿操作11 小时前
Cesium实战:交互式多边形绘制与编辑功能完全指南(最终修复版)
前端·javascript·3d·vue
coding随想13 小时前
JavaScript中的系统对话框:alert、confirm、prompt
开发语言·javascript·prompt
pobu16813 小时前
aksk前端签名实现
java·前端·javascript