Javascript 停止AJAX成功方法中的即时传播

Javascript 停止AJAX成功方法中的即时传播,javascript,jquery,ajax,Javascript,Jquery,Ajax,这是我的密码: $(document).on('click', '[data-submit-form]', function (event) { var form = $(this).closest('form'); $.ajax({ url : form.attr('action'), type : 'post', data: form.serialize(), async: false, suc

这是我的密码:

$(document).on('click', '[data-submit-form]', function (event) {
    var form = $(this).closest('form');

    $.ajax({
        url : form.attr('action'),
        type : 'post',
        data: form.serialize(),
        async: false,
        success: function (data) {
            if ($.type(data) === 'object') {
                alert_errors(form, data);
                event.stopImmediatePropagation()
            }
        }
    });
});
这使用AJAX在单击按钮时检查服务器是否存在错误。如果有错误,它将返回一个包含错误的对象。在发生错误的情况下,我希望停止单击按钮上发生的所有其他事件。例如,该按钮也可用于关闭模式。如果出现错误,我想阻止这种情况发生


这根本不起作用。显示警报后,event.stopImmediatePropagation()似乎对按钮的其他事件没有影响。

如果事件处理已经完成,则无法阻止事件处理。事件顺序如下:

用户单击按钮

  • 立即:
  • 发送AJAX请求
  • 其余的处理完成了
  • 几毫秒后:(已编辑)会收到AJAX响应,但会忽略回调,因为此调用是同步的
基于此,您的代码应该类似于:

$(document).on('click', '[data-submit-form]', function (event) {
    var form = $(this).closest('form');

    var data= JSON.parse(
        $.ajax({
           url : form.attr('action'),
           type : 'post',
           data: form.serialize(),
           async: false
        }).responseText; //The ajax call returns the response itself

    if ($.type(data) === 'object') {
        alert_errors(form, data);
        //event.stopImmediatePropagation()
    } else {
        //rest of the event handling
    }
});

但是无论如何,我认为您应该使用异步调用,因为浏览器甚至jQuery都不赞成使用同步调用(文档已经删除了所有同步示例,不鼓励使用它)

当处理已经完成时,您无法阻止事件处理。事件顺序如下:

用户单击按钮

  • 立即:
  • 发送AJAX请求
  • 其余的处理完成了
  • 几毫秒后:(已编辑)会收到AJAX响应,但会忽略回调,因为此调用是同步的
基于此,您的代码应该类似于:

$(document).on('click', '[data-submit-form]', function (event) {
    var form = $(this).closest('form');

    var data= JSON.parse(
        $.ajax({
           url : form.attr('action'),
           type : 'post',
           data: form.serialize(),
           async: false
        }).responseText; //The ajax call returns the response itself

    if ($.type(data) === 'object') {
        alert_errors(form, data);
        //event.stopImmediatePropagation()
    } else {
        //rest of the event handling
    }
});

但是无论如何,我认为您应该使用异步调用,因为浏览器甚至jQuery都不赞成使用同步调用(文档已经删除了所有同步示例,不鼓励使用它)

这里的问题与同步或异步代码无关

是的,如果AJAX调用是异步的,那么这将是一个问题,因为事件委派是同步的,不会等待AJAX调用返回。但是您的调用是同步的,因为您设置了
async:true

这里真正的根本问题是时间

您正在发出的HTTP请求——即使它是同步的,因为您设置了
async:false
——需要时间才能完成,并且在完成时,浏览器的事件委派已经发生,因此您的
event.stopImmediatePropagation()
无效

理想情况下,您需要将
事件.stopImmediatePropagation
移动到另一个位置,如下所示:

$(document).on('click', '[data-submit-form]', function (event) {
    var form = $(this).closest('form');

    event.stopImmediatePropagation(); // Do it here

    $.ajax({
        url : form.attr('action'),
        type : 'post',
        data: form.serialize(),
        async: false,
        success: function (data) {
            if ($.type(data) === 'object') {
                alert_errors(form, data);
                // event.stopImmediatePropagation() NOT here
            }
        }
    });
});
// By default, this will NOT close the modal anymore. You must explicitly
// call 'closeModal' where you want, e.g. in the AJAX success callback.
// This type of granularity will be much more flexible and save you headache.
$(document).on('click', '[data-submit-form]', function (event) {
    var form = $(this).closest('form');

    $.ajax({
        url : form.attr('action'),
        type : 'post',
        data: form.serialize(),
        async: false,
        success: function (data) {
            if ($.type(data) === 'object') {
                alert_errors(form, data);
                closeModal(); // Close modal
            }
        }
    });
});
编辑

您当前的方法并不是执行您正尝试执行的操作的最理想方式,因为模式关闭和表单提交逻辑的耦合过于紧密,因为它们位于同一个单击事件中

与同时关闭模式的submit form click事件不同,您应该使用单独的功能使流程稍微细化一些:

  • 一个用于处理按钮的单击事件并提交表单
  • 一个关闭模态,可以从任何地方调用
使用这种方法,您的代码可以保持原样,并在成功回调中调用closeModal函数,如下所示:

$(document).on('click', '[data-submit-form]', function (event) {
    var form = $(this).closest('form');

    event.stopImmediatePropagation(); // Do it here

    $.ajax({
        url : form.attr('action'),
        type : 'post',
        data: form.serialize(),
        async: false,
        success: function (data) {
            if ($.type(data) === 'object') {
                alert_errors(form, data);
                // event.stopImmediatePropagation() NOT here
            }
        }
    });
});
// By default, this will NOT close the modal anymore. You must explicitly
// call 'closeModal' where you want, e.g. in the AJAX success callback.
// This type of granularity will be much more flexible and save you headache.
$(document).on('click', '[data-submit-form]', function (event) {
    var form = $(this).closest('form');

    $.ajax({
        url : form.attr('action'),
        type : 'post',
        data: form.serialize(),
        async: false,
        success: function (data) {
            if ($.type(data) === 'object') {
                alert_errors(form, data);
                closeModal(); // Close modal
            }
        }
    });
});
这样的方法更简洁,因为随着功能的不断增长,您会发现自己遇到越来越多的奇怪场景,在这些场景中,您希望调用
预防性失效
停止传播
停止即时传播
,等等,我保证你会再次遇到同样的问题。那只会是一团糟


现在省去麻烦吧。

这里的问题与同步或异步代码无关

是的,如果AJAX调用是异步的,那么这将是一个问题,因为事件委派是同步的,不会等待AJAX调用返回。但是您的调用是同步的,因为您设置了
async:true

这里真正的根本问题是时间

您正在发出的HTTP请求——即使它是同步的,因为您设置了
async:false
——需要时间才能完成,并且在完成时,浏览器的事件委派已经发生,因此您的
event.stopImmediatePropagation()
无效

理想情况下,您需要将
事件.stopImmediatePropagation
移动到另一个位置,如下所示:

$(document).on('click', '[data-submit-form]', function (event) {
    var form = $(this).closest('form');

    event.stopImmediatePropagation(); // Do it here

    $.ajax({
        url : form.attr('action'),
        type : 'post',
        data: form.serialize(),
        async: false,
        success: function (data) {
            if ($.type(data) === 'object') {
                alert_errors(form, data);
                // event.stopImmediatePropagation() NOT here
            }
        }
    });
});
// By default, this will NOT close the modal anymore. You must explicitly
// call 'closeModal' where you want, e.g. in the AJAX success callback.
// This type of granularity will be much more flexible and save you headache.
$(document).on('click', '[data-submit-form]', function (event) {
    var form = $(this).closest('form');

    $.ajax({
        url : form.attr('action'),
        type : 'post',
        data: form.serialize(),
        async: false,
        success: function (data) {
            if ($.type(data) === 'object') {
                alert_errors(form, data);
                closeModal(); // Close modal
            }
        }
    });
});
编辑

您当前的方法并不是执行您正尝试执行的操作的最理想方式,因为模式关闭和表单提交逻辑的耦合过于紧密,因为它们位于同一个单击事件中

与同时关闭模式的submit form click事件不同,您应该使用单独的功能使流程稍微细化一些:

  • 一个用于处理按钮的单击事件并提交表单
  • 一个关闭模态,可以从任何地方调用
使用这种方法,您的代码可以保持原样,并在成功回调中调用closeModal函数,如下所示:

$(document).on('click', '[data-submit-form]', function (event) {
    var form = $(this).closest('form');

    event.stopImmediatePropagation(); // Do it here

    $.ajax({
        url : form.attr('action'),
        type : 'post',
        data: form.serialize(),
        async: false,
        success: function (data) {
            if ($.type(data) === 'object') {
                alert_errors(form, data);
                // event.stopImmediatePropagation() NOT here
            }
        }
    });
});
// By default, this will NOT close the modal anymore. You must explicitly
// call 'closeModal' where you want, e.g. in the AJAX success callback.
// This type of granularity will be much more flexible and save you headache.
$(document).on('click', '[data-submit-form]', function (event) {
    var form = $(this).closest('form');

    $.ajax({
        url : form.attr('action'),
        type : 'post',
        data: form.serialize(),
        async: false,
        success: function (data) {
            if ($.type(data) === 'object') {
                alert_errors(form, data);
                closeModal(); // Close modal
            }
        }
    });
});
这样的方法更简洁,因为随着功能的不断增长,您会发现自己遇到越来越多的奇怪场景,在这些场景中,您希望调用
预防性失效
停止传播
停止即时传播
,等等,我保证你会再次遇到同样的问题。那只会是一团糟


现在省去你的麻烦。

尝试使用.done和.faile。在我给你建议之前,有一个问题,为什么你要使用on('click')而不是更具体的选择器,比如$(#form)。使用
提交(..)。done
的结果完全相同。我怀疑这是因为你是我们的回调