此次测试是因为网络请求原因,post提交数据后,后台反应比前台慢,所以为了拿到请求数据,post会自动多次请求。我这里是监听视频播放,给用户追加积分。
防止数据重复提交原理:每一轮数据提交的时候,前端建立一个时间戳作为判断数据是否重复的基准。后端执行时,将此次基准时间戳进行session存储,在此次程序执行完毕后,前端拿到返回数据,等待几秒钟再修改下一轮基准时间戳。这里要注意,当我们第二轮时间戳进入后台时,要将前一轮的时间戳删除,存储新的,判断是否为新时间戳很简单,将前一轮的时间戳与新一轮作比较,相等即为旧(为旧说明是重复提交的,直接return 返回,不继续执行),不等即为新。
后台框架thinkphp6:
//追加积分
public function addIntegral(){
$info = input();
//用户id
$uid = $this->uid;
$integral = $info['sy_integral'];
//系统追加积分
//获取当前数据提交的时间,以时间戳作为数据是否提交的基准,当数据提交进来的时候,存储当前数据提交时间,执行后续操作,前端在数据返回后稍微等待几秒钟再做第二轮数据提交时间的修改。
if(!empty(session::get('isSubmit'))){
//session::set('isSubmit',$info['timestamp']);
//}else{
//判断当前数据提交时间是否等于上一次提交,如果相等说明是后端还未返回数据前端重复提交的,此时直接返回,停止重复请求,如果两次数据提交时间不相等,说明这是一轮新的数据提交,此时需要删除记录的上一轮数据提交时间,重新存储此次的数据提交时间,以此类推……
if(session::get('isSubmit') == $info['timestamp']){
return false;
//return json(['info'=>'积分追加错误,数据重复','status'=>0]);
}else{
//删除session
//session::delete('isSubmit');
session::set('isSubmit',$info['timestamp']);
}
}
$res = Db::name('users')->where('us_id',$uid)->inc('us_integral')->update();
if($res){
integralAdd($uid,'观看微课堂视频+'.$integral,1,$integral);
return json(['info'=>'你观看了10分钟视频,奖励您'.$integral.'个积分','status'=>1]);
}else{
return json(['info'=>'积分追加错误','status'=>0]);
}
}
前端js代码:
//监听播放时间变化,追加积分
var sy_integral = Number("{$sy_integral}"); //每次观看视频追加的积分
var date = new Date();
var timestamp = date.valueOf(); //时间戳
$("#input").val(timestamp); //隐藏时间戳,这个input输入框可自行在页面输入,使用隐藏域
$("video").on("timeupdate",function(even){ //监听视频播放时间
var num = Math.floor(this.currentTime); //视频播放时间
var time = $("#input").val(); //获取此次数据提交的时间
if(num > 0 && num % 60 == 0){
$.post("{:url('Video/addIntegral')}",{'sy_integral':sy_integral,'timestamp':time},function(res){
if(res.status == 1){
mui.toast(res.info,{ duration: 1500, type:'div' });
//3S后执行,稍微等待几秒钟后再修改下一轮数据提交的基准时间
setTimeout(function(){
$("#input").val((new Date()).valueOf()); //时间戳
},3000);
return true;
}else{
//mui.toast(res.info,{ duration: 1500, type:'div' });
return false;
}
},'json');
}
// 总时长
//$("#duration").val(Math.floor(this.duration));
});