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.