就在那时,我即将重写我们的JavaScript系统,我们正在从Prototype转向jQuery。我们有一大堆AJAX请求在某个元素事件发生时触发,下面示例中的一个是日历上的新事件,但它也发生在其他地方。
我遇到的问题是当事件被触发时有时会发出两个AJAX请求。第一个返回正确的值,但(如您所见)它仍然表示处理,它永远不会返回我的JavaScript所需的成功消息。第二个请求返回正确的结果并正确终止。
我遇到的问题是我们的jQuery屏幕拦截器被设置为在重大的AJAX请求期间阻止用户输入,显然是因为有一个AJAX请求仍然存在,屏幕永远不会解锁。如果我要刷新此屏幕,则所有内容都将按预期工作。
任何人都可以解释为什么会发生这种行为。
alt text http://archive.ilmv.co.uk/images/jquery-duplicate-ajax-request.png
修改
“请求在某个元素事件发生时触发” - 这是关键短语,我想。请提供有关如何设置活动的一些信息。也许它会因为你有多个处理程序而触发两次? - Igor Zinov'yev
好的,就是当我点击刷新时,问题通常会自行解决,所以不确定这可能是一个处理程序问题,这里是我们通常用于更改选择框的事件处理程序。
$("#my_select","#context").change(function(){
// uz_ajax is a wrapper function, keeps most of the same functionality as $.ajax()
uz_ajax({
target:"#my_target",
data:{
module:'my_module',
controller:'my_controller',
action:'my_action',
id:$(this).val(),
ajax:''
}
});
});
我遇到的问题是我不知道如何复制问题,因此我不知道该事件是否被多次触发或者AJAX是否请求了两次。
编辑2
如果要重新加载那些元素 然后变化事件可以绑定 递归触发...我们真的 需要查看更多代码(你做了什么 关于ajax电话的成功等) - redsquare
感谢redsquare,在成功的AJAX请求后,我通常会将响应(通常是<option>
s的HTML)应用于目标。我永远不会从触发AJAX的元素触发更改,但我有时会触发对目标元素的更改,以允许级联AJAX请求。如果这是问题,肯定会一直发生这种情况?我的包装函数uz_ajax
如下:
var ajax_count = 0;
var ajax_response = null;
function uz_ajax(options) {
// set default options
var defaults = {
async: true,
type: "GET",
data: {},
url: "/",
cache: false,
force_change: true,
highlight: true,
action: "normal",
dataType: "html",
selected: {
value: null,
disabled: false
}
};
// merge the passed options with the defaults
var options = $.extend(defaults, options);
// start the jQuery ajax method
$.ajax({
async: options.async,
type: options.type,
url: options.url,
data: options.data,
beforeSend: function() {
// we only want to block the screen on the first pass
if(++ajax_count==1) {
$.blockUI({message:'Loading data, please wait'});
}
},
success: function(responseText) {
if(options.target!==undefined) {
// if target isn't an array, make it one
if(!$.isArray(options.target)) {
options.target = new Array(options.target);
}
var targets = options.target;
for ( var i in targets ) {
console_info("uz_ajax() --> Applying contents to "+targets[i]);
switch(options.action) {
case "normal":
if($(targets[i]).is("input")) {
$(targets[i]).val(trim(responseText));
} else {
$(targets[i]).html(trim(responseText));
}
break;
case "selected":
// preserve the current target value (e.g. list of options), but
// set the selected value to the ajax response
console_warn("Changing selected value of "+targets[i]+" to '"+responseText+"'");
// trim the response so we don't get any smarty induced errors such as ' 7'
$(targets[i]).val(trim(responseText));
break;
}
// set selected value
if(options.selected.value!=null) {
$(targets[i]).val(options.selected.value);
}
// highlight the target
// we don't want to highlight the target if it's a hidden input, as this will force a .show(
if($(targets[i]).attr('type')!='hidden' && options.highlight===true) {
$(targets[i]).effect("highlight",{},2000);
}
// force the target to change
if(options.force_change===true) {
$(targets[i]).trigger("change");
}
/* rebind certain elements that do not use conventional events */
/* We probably need to get all of these rebinds in a single function */
createDatePickers(targets[i]);
}
} else {
ajax_response = responseText;
console_warn("uz_ajax -> no targets specified");
// Well... we have no element to target, we need to return the value instead
// of course if we return here we're going
// we probably also need to check the ajax count as this will be the last executed part before we return
}
},
complete: function () {
/* if all ajax requests have completed, unblock screen */
if(--ajax_count===0) {
$.unblockUI();
/* could use this callBack to return a value *dun dun duuuuun* */
if (options.ajaxComplete) {
options.ajaxComplete(ajax_response);
}
}
},
cache: options.cache,
dataType: options.dataType
});
}
另一种停止多个ajax的方法 请求是heck jQuery.active 在通话之前。 jQuery保持着 “实时”ajax请求的内部计数 使用此属性。 - redsquare
我会调查一下。
编辑3
所以这是$('element')。data()的结果,但是我无法理解它想说的是什么,这是否意味着它有两种结合。如果是这样,我如何找出这些绑定是什么以及为什么它们都不会在事件被触发时触发。
alt text http://archive.ilmv.co.uk/images/firebug-jquery-data-events.png
编辑4
这是问题的另一个屏幕截图,这次是在系统的另一个地方。绿色箭头是触发三个ajax请求的元素,而不是在firebug中如何有六个,并且它们配对并将时间戳分配到毫秒?
前三位是尚未完成的,前三位是返回正确的结果。
alt text http://archive.ilmv.co.uk/images/jquery-duplicate-ajax-request-v2.png
编辑5
下图显示了更改选择框时会发生什么,它会触发三个不同的ajax请求。
我设法做了一些调试,我可以告诉你以下内容:
console.info
回调中添加了$.ajax()
,以查看触发的内容和时间,请注意唯一的触发回调是beforeSend()
。alt text http://archive.ilmv.co.uk/images/jquery-duplicate-ajax-request-v3.png
编辑6
就在那之后,@ redsquare通过Twitter建议使用console.trace()
找出“第二个事件从哪里开火”,就像我一直坚持的那样,我确信没有两个事件发生所以我把跟踪放在$.ajax()
方法中,这就是发生的事情:
alt text http://archive.ilmv.co.uk/images/jquery-duplicate-ajax-request-v4.png
正如您所看到的,即使$.ajax()
方法仅触发一次,我也会收到重复的ajax请求问题,时间戳也是相同的。我遇到过jQuery的错误吗?
编辑7
它也发生在StackOverflow上!
alt text http://archive.ilmv.co.uk/images/jquery-duplicate-ajax-request-v5.png
答案 0 :(得分:1)
您是否尝试过使用.click()?我在javascript中使用.change()遇到了不规则活动的问题。试一试。
答案 1 :(得分:1)
是的,所以我得出了一个结论,我很确定我的问题是Firebug的一个问题,因为我已经在FF上测试了它没有启用Firebug的应用程序,它可以正常工作。
当问题所引发的症状没有给解决方案提供任何合理的暗示时,这不是JavaScript相关的第一次引发我欢快的舞蹈,但我们有它。
非常感谢@redsquare,他们在这里大力帮助,但通过Twitter和jQuery IRC频道,非常感谢老兄!
答案 2 :(得分:0)
尝试将return false
添加到您的onchange函数中。
这将阻止jQuery冒泡事件。
您应确保$("#my_select","#context").change(function(){
仅被调用一次。
答案 3 :(得分:0)