jQuery事件处理程序如何排队和执行?

Hoo*_*ini 18 html javascript jquery form-submit

我有一个输入表单,带有一个提交按钮。我不希望用户能够双击提交按钮并再次提交表单...

因此,我将以下jQuery添加到了Form中:

var prevSubmitTime = new Date('2000-01-01');

function preventFromBeingDoubleSubmitted() {
    $('form').each(function () {
        $(this).submit(function (e) {
            if ($("form").valid()) {
                var curSubmitTime = new Date($.now());

                // prevent the second submit if it is within 2 seconds of the first submit
                if (curSubmitTime - prevSubmitTime < 2000) {
                    e.preventDefault();
                }
                prevSubmitTime = new Date($.now());
            }
        });
    });
}

$(document).ready(function () {
    preventFromBeingDoubleSubmitted();
});
Run Code Online (Sandbox Code Playgroud)

上面的代码存储了提交时间并阻止了第二次提交,如果为时过早(少于2秒),我不想永久禁用提交按钮,以防服务器端发生错误...

这段代码可以实现我想要的功能,但是在调试代码时,e.preventDefault();即使双击提交按钮,也永远无法达到断点。

看起来第二个提交事件正在等待第一个提交事件完成,然后再触发。

但是,如果删除preventFromBeingDoubleSubmitted()功能,则可以通过双击提交按钮来两次提交表单。

谁能解释为什么有时候提交事件被一个接一个地触发……有时候却不是这样吗?将事件处理程序放进去.each(),会影响它们的执行行为吗?

Pat*_*ans 4

表单在提交时默认导航到设置的actionurl。如果未明确设置,则 url 为当前页面。第一次提交调用最终将启动导航过程。在此期间,当前加载的 JavaScript 代码将被卸载。这包括事件处理程序。因此,为什么你会得到是否能够双重提交的不一致。如果网络请求和其他页面处理对操作 url 的发生速度快于您再次单击事件处理程序的速度,并且您的断点将不会再次被调用/到达,因为它们已经被卸载。反之亦然,如果网络请求较慢,您将能够调用处理程序并到达断点(如果尚未卸载)。

您说您不想永久禁用提交按钮,但即使您禁用它,表单提交也会导致页面更改,在您的示例中,这只会加载带有新提交按钮的同一页面,这将不再被禁用,因为它是一个新页面。因此,它从一开始就从未真正被永久禁用。

现在,如果您的真实表单实际上并未执行正常的表单提交,并且您正在使用 ajax 请求、Web 套接字连接等,那么您可以在请求之前将按钮设置为禁用(或设置繁忙标志)并取消设置它在 ajax 请求回调、web 套接字事件等中。

例如:

jQuery('form').on('submit',function(e){
  e.preventDefault();
  var fd = new FormData(this);
  jQuery('yourbutton').prop('disabled',true);
  fetch('url',{method:"post",body:fd}).then(()=>jQuery('yourbutton').prop('disabled',false));
});
Run Code Online (Sandbox Code Playgroud)