JQuery事件正在被另一个事件所取代

时间:2016-08-03 20:17:22

标签: javascript jquery ajax

我有一个实际上由两种形式组成的表格。每个表格都是预订表格。两种形式都有两个下拉列表 - destination fromdestination to。有一个偶数处理程序,当选择/更改目标时,它调用AJAX以使destinations to成为可能。

另一个事件处理程序(往返复选框)通过从第一个表单切换目标来填充第二个表单下拉列表。

所以如果第一个表格有:

destination one: France
destination two: Austria

然后,如果选中round trip,则立即填写第二个表格:

destination one: Austria
destination two: France 

问题在于这两个事件没有正确合作。

执行此代码时:

id_form_1_destination_from.val(destination_to_0.val());
id_form_1_destination_to.val(destination_from_0.val());
id_form_1_destination_from.change();
id_form_1_destination_to.change();

第一行调用另一个填充第二种形式的处理程序(这是唯一不需要它的情况)。由于它是AJAX,第二行超过了这个AJAX,所以现在,第二种形式被正确填充(从第一种形式切换目的地),但是当AJAX完成时,它改变了选择destination two字段。

有没有办法避免这种情况?例如,关闭事件处理程序或更好地使JQuery等待AJAX完成然后继续。我不能在.off()字段上destination to,因为我使用select2插件。

这是我的JQuery

$(document).ready(function () {
    var destination_from_0 = $("#id_form-0-destination_from");
    var destination_to_0 = $('#id_form-0-destination_to');
    var ride_two = $('#ride_two');

    $('.class-destination-from').on('change', function () {
        destination_from_changed.call(this);
    });

    $("#id_round_trip").on('change', function () {

        if (($('#id_round_trip').is(':checked')) ) {

            var id_form_1_destination_from =$('#id_form-1-destination_from');
            var id_form_1_destination_to = $('#id_form-1-destination_to');

            ride_two.show('fast');

            //id_form_1_destination_from.off();
            id_form_1_destination_from.val(destination_to_0.val()).change();
            //id_form_1_destination_from.on();
            //id_form_1_destination_from.change();
           id_form_1_destination_to.val(destination_from_0.val()).change();


        }else{
            ride_two.hide('fast');
            ride_two.find(':input').not(':button, :submit, :reset, :checkbox, :radio').val('').change();
            ride_two.find(':checkbox, :radio').prop('checked', false).change();
        }
    });
    $('.class-destination-to').on('change', destination_to_changed);



});

function destination_to_changed() {
    var destination_id = $(this).val();
    var arrival_container = $(this).siblings('.arrival-container');
    var departure_container = $(this).siblings('.departure-container');

    if (destination_id == '') {
        return;
    }
    $.ajax({
        url: '/ajax/is-airport/' + destination_id + '/',
        success: function (data) {
            if (data.status == true) {
                arrival_container.hide("slow");
                departure_container.show("slow");

            }
            if (data.status == false) {

                departure_container.hide("slow");
                arrival_container.show("slow");
            }
            arrival_container.change();
            departure_container.change();
        }
    })
}

function destination_from_changed() {
    var destination_id = $(this).val();
    if (destination_id == '') {
        return;
    }
    var ajax_loading_image = $('#ajax-loading-image');
    var destination_to = $(this).siblings('.class-destination-to');
    destination_to.empty();
    ajax_loading_image.show();
    $.ajax({
        url: '/ajax/get-destination-to-options/' + destination_id + '/',
        async:false, // ADDED NOW - THIS HELPED BUT IT'S NOT NECESSARY EVERYTIME
        success: function (data) {
            ajax_loading_image.hide();
            destination_to.append('<option value="" selected="selected">' + "---------" + '</option>');
            $.each(data, function (key, value) {
                destination_to.append('<option value="' + key + '">' + value + '</option>');
            });
            destination_to.change();
        }
    })
}

3 个答案:

答案 0 :(得分:2)

如果我理解正确,您就会遇到并发问题。你基本上想要在第二次调用之前终止你的第一个ajax调用吗?

我在代码中没有看到任何ajax请求,但我认为参数 async:false,可能就是您所需要的。

查看文档:{​​{3}}

希望有所帮助

答案 1 :(得分:1)

你肯定会有一个经典的“竞争条件”。

由于AJAX调用看起来彼此无关,因此您可能需要在JavaScript端添加一些代码,以便不会发生潜在的“竞争”情况。例如,要识别组合是“正在填充”,如果您已发出AJAX请求以填充它但尚未获得响应。您可以禁用某些按钮。

顺便说一句,在这种情况下,涉及两个(或更多......)表单,我喜欢尝试集中逻辑。例如,可能存在“单个对象”,其工作是知道在主机上或与主机一起完成的所有事件的当前状态。有限状态机(FSM)(mumble,mumble ......)在这里工作得非常好。该对象可能会广播事件,以便在需要更改按钮等时通知“听众”。

答案 2 :(得分:0)

您需要在开始第二次AJAX请求之前取消它。从这个问题:

Abort Ajax requests using jQuery

var xhr;

function getData() {
  if (xhr) { xhr.abort(); }
  xhr = $.ajax(...);
}