我有一个实际上由两种形式组成的表格。每个表格都是预订表格。两种形式都有两个下拉列表 - destination from
和destination 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();
}
})
}
答案 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(...);
}