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的代码如下:

//---------------------------------------------------------
// 作者:野文(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;
                }
            }
        );
    }
);

    效果如下:

    AvoidRepeatSubmit-通过Javascript避免客户端重复提交请求

    示例Demo代码下载AvoidRepeatSubmit.

相关文章: