小程序
小游戏
企业微信
微信支付
扫描小程序码分享
目前的解决办法是在js里限制提交,首先有一个点击事件的开关,当这个开关为N的时候可进行提交,为Y的时候不能提交,其次就是加了一个时间判断,两次提交时间不能小于3秒,否则也认为是重复提交,但是这样都在后台看到有重复提交数据上传,有大佬知道是什么原因吗?代码如下
代码片段:https://developers.weixin.qq.com/s/grIUofma7qJ3
有大佬能完美解决奉上红包一个
6 个回答
加粗
标红
插入代码
插入链接
插入图片
上传视频
前端做个防抖,后端可以做个接口幂等
你好,麻烦通过点击下方“反馈信息”按钮,提供出现问题的。
如果是提交数据到后台,后台判断这个用户有没有提交过(该表里边有没有这个用户的数据),如果有提交,不让提交;如果是需要多次提交的,后台同样判断时间差,多久允许提交一次;
一般来讲,你这个逻辑是没有问题的,但为什么做了限制,仍然会提交两次呢?两种可能
1.该方法是异步调用的,异步调用就意味着存在多条线程同时运行,当还是y的时候,就有两个或以上线程运行到方法里了,这种情况你给方法设为同步调用就行了;
2.虽然你设置了时间3s,但你要考虑到,这小段代码运行是毫秒级别的,你设置一个Y参数,还用断位或.你后面的3s就没有起作用,这种情况,你删除那个Y参数,只保留一个3s的条件就可以了
3.补充一点,这种判断,你直接过滤掉就好了,从用户角度来讲,我点一次,你也正常提交了,但是你还给我一个错误点击的提示,会让我误以为我的操作没有生效
参考下我的封装
https://www.cnblogs.com/520BigBear/p/16328212.html
/** * 是否重复点击 */ class RepeatClick { constructor() { this.clickTime = 0; } isRepeat() { return 1 === this.clickTime; } begin() { this.clickTime = 1; } end() { this.clickTime = 0; } } module.exports = { RepeatClick } //////////////////////////////// import { RepeatClick } from './RepeatClick'; /** * 间隔多久可再次执行 */ class IntervalLoad { constructor() { this.repeat = new RepeatClick(); } /** * 完成标记 * @param {number} interval 间隔时间 * @param {string} toast 提示信息,'none' 不提示 * @param {boolean} toastMask 是否显示提示蒙层 * @return true可以再次执行,false不可再次执行 */ done(p = { interval: 1500, toast: '请勿频繁操作', toastMask: true }) { if (this.repeat.isRepeat()) { if ('none' != p.toast) { wx.showToast({ title: p.toast, icon: 'none', mask: p.toastMask }); } return false; } this.repeat.begin(); const that = this; // interval秒后可以重新加载 setTimeout(function () { that.repeat.end(); }, p.interval); return true; } } module.exports = { IntervalLoad } /////////////使用 import { IntervalLoad } from 'IntervalLoad'; const $interval = new IntervalLoad(); submit() { if (!$interval.done()) { return; } }
button有个disabled属性,设置它比showLoading靠谱
关注后,可在微信内接收相应的重要提醒。
请使用微信扫描二维码关注 “微信开放社区” 公众号
前端做个防抖,后端可以做个接口幂等
如果是提交数据到后台,后台判断这个用户有没有提交过(该表里边有没有这个用户的数据),如果有提交,不让提交;如果是需要多次提交的,后台同样判断时间差,多久允许提交一次;
一般来讲,你这个逻辑是没有问题的,但为什么做了限制,仍然会提交两次呢?两种可能
1.该方法是异步调用的,异步调用就意味着存在多条线程同时运行,当还是y的时候,就有两个或以上线程运行到方法里了,这种情况你给方法设为同步调用就行了;
2.虽然你设置了时间3s,但你要考虑到,这小段代码运行是毫秒级别的,你设置一个Y参数,还用断位或.你后面的3s就没有起作用,这种情况,你删除那个Y参数,只保留一个3s的条件就可以了
3.补充一点,这种判断,你直接过滤掉就好了,从用户角度来讲,我点一次,你也正常提交了,但是你还给我一个错误点击的提示,会让我误以为我的操作没有生效
有一个bug是我做另一个项目发现的,在使用小程序<movable-area>组件时,内部如果存在输入框,在输入完成时触发输入完成事件,调用方法会直接调用两次,用上面那种方法完全防不住,但是这种情况只在Android机型上出现。所以我现在怀疑在按钮那里是不是点击就直接同时触发了两次方法调用。目前后台看到的数据大概有千分之一的概率是重复提交
参考下我的封装
https://www.cnblogs.com/520BigBear/p/16328212.html
/** * 是否重复点击 */ class RepeatClick { constructor() { this.clickTime = 0; } isRepeat() { return 1 === this.clickTime; } begin() { this.clickTime = 1; } end() { this.clickTime = 0; } } module.exports = { RepeatClick } //////////////////////////////// import { RepeatClick } from './RepeatClick'; /** * 间隔多久可再次执行 */ class IntervalLoad { constructor() { this.repeat = new RepeatClick(); } /** * 完成标记 * @param {number} interval 间隔时间 * @param {string} toast 提示信息,'none' 不提示 * @param {boolean} toastMask 是否显示提示蒙层 * @return true可以再次执行,false不可再次执行 */ done(p = { interval: 1500, toast: '请勿频繁操作', toastMask: true }) { if (this.repeat.isRepeat()) { if ('none' != p.toast) { wx.showToast({ title: p.toast, icon: 'none', mask: p.toastMask }); } return false; } this.repeat.begin(); const that = this; // interval秒后可以重新加载 setTimeout(function () { that.repeat.end(); }, p.interval); return true; } } module.exports = { IntervalLoad } /////////////使用 import { IntervalLoad } from 'IntervalLoad'; const $interval = new IntervalLoad(); submit() { if (!$interval.done()) { return; } }
button有个disabled属性,设置它比showLoading靠谱