Web项目上线后当访问压力增大时,处理速度往往比在测试环境时慢好多倍。当用户点击页面控件提交请求半天没反应时,他就会不停的重复点击该控件,造成请求的重复提交,这个时候很多问题就暴露出来了。上个项目是用Asp.net+C#开发的,为了避免这个重复提交问题,在以前的一个js版本上做了一些完善,虽然技术比较传统,但还是能做为应急之用。
Asp.net客户端提交的路径分为以下几种:
- a) 点button提交 -> form的onsubmit事件
b) 点button提交 -> button的WebForm_DoPostBackWithOptions ->form的WebForm_OnSubmit(包含了自定义的submit事件) - c) 点button -> __doPostBack -> 运行form的onsubmit –> submit
d) 点button -> WebForm_DoPostBackWithOptions -> __doPostBack -> 运行form的onsubmit(WebForm_OnSubmit) –> submit
该js的代码如下:
Code//--------------------------------------------------------- // 作者:野文(Jasson) http://qguohog.cnblogs.com // 日期:2010-12-18 // 功能:避免重复提交数据。若某个按钮控件不需要启用重复提交, // 则在其上添加属性AvoidRepeatSubmit="false" //--------------------------------------------------------- $(document).ready( function() { var isPosting = false; var divMask = null; var divTipContent = null; var formOnSubEvts = new Object(); var submitByClickCtrl = null; function _doPostBack() { }; if (typeof (__doPostBack) == "function") { _doPostBack = __doPostBack; __doPostBack = _doPostBackNew; } function _doPostBackNew(sender, args) { try { submitByClickCtrl = $("#" + sender); } catch (e) { try { submitByClickCtrl = $("#" + sender.replace('$', '_')); } catch (ex) { submitByClickCtrl = null; } } _doPostBack(sender, args); } function createLayerMask() { if (divMask == null) { divMask = $("<div tabindex='0'></div>"); $(divMask).addClass("arsMask"); $(document.body).append(divMask); bindEvents(divMask); } } function createTipContent() { if (divTipContent == null) { divTipContent = $("<div></div>"); $(divTipContent).addClass("arsTipContent"); $(document.body).append(divTipContent); bindEvents(divTipContent); } } function bindEvents(divObj) { $(divObj).blur(function() { this.focus(); }); $(divObj).bind("drag", function() { return false; }); $(divObj).bind("selectstart", function() { return false; }); $(divObj).bind("contextmenu", function() { return false; }); $(divObj).bind("focus", function() { this.blur(); }); } function setLocation() { $(divMask).height(document.documentElement.scrollTop + document.documentElement.clientHeight); $(divMask).width(document.documentElement.scrollLeft + document.documentElement.clientWidth); $(divTipContent).css("left", document.documentElement.scrollLeft + (document.documentElement.clientWidth - $(divTipContent).width()) / 2); $(divTipContent).css("top", document.documentElement.scrollTop + (document.documentElement.clientHeight - $(divTipContent).height()) / 2); } function showMaskAndTipContent(isShow) { isPosting = isShow; createLayerMask(); createTipContent(); if (isShow) { setProgressInfo(); $(divMask).show(); $(divTipContent).show(); setLocation(); $(window).bind("scroll", setLocation); $(window).bind("resize", setLocation); } else { $(divMask).hide(); $(divTipContent).hide(); $(window).unbind("scroll", setLocation); $(window).unbind("resize", setLocation); } } function setProgressInfo(text, width, height) { if (divTipContent != null) { proText = text || "处理中,请稍候..."; proWidth = width || 140; proHeight = height || 40; $(divTipContent).html(proText); $(divTipContent).width(proWidth); $(divTipContent).height(proHeight); } } function useAvoidRepeatSubmit(ctl) { var avoid = $(ctl).attr("AvoidRepeatSubmit"); return (typeof (avoid) == "undefined" || avoid.toLowerCase() != "false"); } $("input[type=submit],input[type=image]").click( function() { submitByClickCtrl = this; } ); $("form").each( function() { var eSubmit = this.onsubmit; if (typeof (this.onsubmit) == "function") { formOnSubEvts[$(this).attr("name")] = eSubmit; this.onsubmit = null; } this.onsubmit = function(e) { var evt = e || window.event; if (isPosting && evt != null) { return evt.returnValue = !(evt.cancelBubble = true); } var eSubmit = formOnSubEvts[$(this).attr("name")]; if (typeof (eSubmit) == "function" && !eSubmit()) { return false; } if (submitByClickCtrl != null) { if (useAvoidRepeatSubmit(submitByClickCtrl)) { showMaskAndTipContent(true); } } return true; } } ); } );
效果如下:
示例Demo代码下载:AvoidRepeatSubmit.