一.首先说说为什么要防止ajax重复提交,有时候我们会遇到一下几种情况:
情况1:点击一次按钮就会发送一次ajax请求,用户疯狂的快速点击该按钮,密且快的ajax请求会让我们的服务器压力山大。我们必须采取一定的机制防止。
情况2:用户点击不那么频繁,但是第一请求的数据量较多,花费的时间较长,第二次请求的数据较少,比第一次请求的数据早回来,先显示在界面上,等到第一次的数据回来之后,再把数据显示,就会覆盖掉第二次的显示的数据,这样让用户体验很不好。
现在根据个人水平总结了一下几种办法。
二. 解决ajax重复提交请求的办法
1. 让其点击的按钮disable,让其不能点击
这儿以登录按钮为例
(function($){ $('.J-login').click(function(){ varloginBtn=this; //1.先进行表单验证 //...... //2.让提交按钮失效,以实现防止按钮重复点击 $(loginBtn).attr('disabled','disabled'); //3.给用户提供友好状态提示 $(loginBtn).text('登录中...'); //4.异步提交 $.ajax({ url:'login.do',data:$(this).closest('form[name="loginForm"]').serialize(),type:'post',success:function(msg){ if(msg==='ok'){ alert('登录成功!'); //TODO其他操作... }else{ alert('登录失败,请重新登录!'); //5.让登陆按钮重新有效 $(loginBtn).removeAttr('disabled'); } } }); }); })(jQuery);
当然,我们可以用一个更加优雅的方式来代替之。
(function($){ $('.J-login').click(function(){ varloginBtn=this; //1.先进行表单验证 //...... //2.异步提交 $.ajax({ url:'login.do',beforeSend:function(){ //3.让提交按钮失效,以实现防止按钮重复点击 $(loginBtn).attr('disabled','disabled'); //4.给用户提供友好状态提示 $(loginBtn).text('登录中...'); },complete:function(){ //5.让登陆按钮重新有效 $(loginBtn).removeAttr('disabled'); },success:function(msg){ if(msg==='ok'){ alert('登录成功!'); //TODO其他操作... }else{ alert('登录失败,请重新登录!'); } } }); }); })(jQuery);
2 用setTimeout+clearTimeout方法,防止大量重复点击
相信大家碰到过这样的业务,我们允许它重复点击(或者其他用户事件),但是不允许在一定的时间内超过次数XX次。这从用户友好体验及服务器承受压力选取了一个折中方案。
vartimer=null; $(input).keyup(function(){ varvalue=$(this).val(); clearTimeout(timer); //如果键盘敲击速度太快,小于100毫秒的话就不会向后台发请求,但是最后总会进行一次请求的。 timer=setTimeout(function(){ //触发请求 $.ajax({ url:'typeahead.do',type:'get',data:value,success:function(){ //显示匹配结果 //......} }); },100); });
这种办法的方法就是当用户疯狂的快速点击的时候,只要时间没有查过100毫秒,就会被取消,只有最后一次会被发送出去。
3 每次发送ajax前,取消之前没有返回的同样的ajax请求,就是abort掉
其实Ajax请求的XMLHttpRequest对象有abort方法,在发送之前把之前没有返回的ajax请求取消。
abort()函数
取消当前响应,关闭连接并且结束任何未决的网络活动。
这个方法把 XMLHttpRequest 对象重置为 readyState 为 0 的状态,并且取消所有未决的网络活动。例如,如果请求用了太长时间,而且响应不再必要的时候,可以调用这个方法。
伪代码如下:
if(xmlhttp&&xmlhttp.readyState<4) { xmlhttp.abort(); }
三 .总结
第1种方法一般用于表单提交数据,防止重复提交,像登陆按钮之类的东西。但不适合与请求资源,用户体验不好
第2种方法是做防止用户疯狂快速点击时产生的大量ajax请求,适合用于请求资源之类的地方使用,但是解决不了情况2的这种情况。
第3中方法适合于也是请求资源,且可以解决就是点击不频繁,且第二个请求比第一个早回来的情况。那为什么请求资源的时候不都用这种办法呢?