在AJAX成功方法中停止立即传播

时间:2017-08-18 14:52:21

标签: 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,
        success: function (data) {
            if ($.type(data) === 'object') {
                alert_errors(form, data);
                event.stopImmediatePropagation()
            }
        }
    });
});

单击按钮时,使用AJAX检查服务器是否有错误。如果有错误,则返回包含错误的对象。如果出现错误,我想停止在单击的按钮上发生所有其他事件。例如,该按钮也可用于关闭模态。如果有错误,我想阻止这种情况发生。

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

2 个答案:

答案 0 :(得分:2)

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

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

这里真正的潜在问题是时间

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

理想情况下,您需要将event.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
            }
        }
    });
});

修改

您当前的方法并不是您尝试做的最理想的方法,因为您的模态关闭和表单提交逻辑太紧密耦合,因为它们处于相同的单击事件中。

您应该使用单独的函数使进程略微更精细,而不是使提交表单单击事件也关闭模式:

  • 一个用于处理按钮的点击事件并提交表单
  • 关闭模式,可以从任何地方调用

使用这种方法,您的代码可以保持原样,并在成功回调中调用closeModal函数,如下所示:

// 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
            }
        }
    });
});

这样的方法更加清晰,因为随着您的功能的增长和增长,您将不断发现自己需要调用preventDeafultstopPropagation的越来越多的奇怪场景, stopImmediatePropagation,等等,我保证你会再次遇到同样的问题。这只会是一团糟。

现在为自己省去麻烦。

答案 1 :(得分:0)

在处理完成后,您无法阻止事件处理。事件的顺序如下:

用户点击按钮

  • 立即:
    1. 发送AJAX请求。
    2. 剩下的处理完成了。
  • 几毫秒后:(已编辑)收到AJAX响应但忽略了回调,因为此调用是同步的。

基于此response,您的代码应该是:

$(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都不推荐使用同步调用(文档已经删除了所有同步示例并阻止了它的使用)