防重复提交

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
},
相关推荐
神仙姐姐QAQ3 分钟前
vue3更改.el-dialog__header样式不生效
前端·javascript·vue.js
AI_56786 分钟前
Vue.js 深度开发指南:从数据绑定到状态管理的最佳实践
前端·javascript·vue.js
前端-文龙刚9 分钟前
浅记Vue3中 ref 和 reactive 是两种主要的响应式数据声明方式,它们有以下主要区别
前端·javascript·vue.js
小先生81210 分钟前
关于vue-element-plus-admin的mini分支踩坑集锦
前端·vue.js·前端框架·c#
hhcccchh11 分钟前
学习vue第十天 V-Model学习指南:双向绑定的魔法师
前端·vue.js·学习
无羡仙8 小时前
从零构建 Vue 弹窗组件
前端·vue.js
源心锁9 小时前
👋 手搓 gzip 实现的文件分块压缩上传
前端·javascript
phltxy10 小时前
从零入门JavaScript:基础语法全解析
开发语言·javascript
Kagol10 小时前
JavaScript 中的 sort 排序问题
前端·javascript
计算机毕设VX:Fegn089511 小时前
计算机毕业设计|基于springboot + vue动物园管理系统(源码+数据库+文档)
数据库·vue.js·spring boot·后端·课程设计