admin管理员组文章数量:1398536
Right then, I'm ing to the end of a rewrite of our JavaScript system, we're moving from Prototype to jQuery. We have a load of AJAX requests that fire when a certain element events occur, the one in the example below is a new event on a calendar, but it happens elsewhere too.
The problem I'm getting is when an event is fired sometimes two AJAX requests are made. The first one returns the correct value but (as you can see) it still says processing, it never returns the success message my JavaScript requires. The second request returns the correct result AND terminates correctly.
The problem I have is our jQuery screen blocker is set up to prevent user input during heavy AJAX requests, obviously because there an AJAX request still live the screen never unlocks. If I were to refresh this screen all will work as desired.
Can anyone shed any light on why this behavior is occuring.
alt text .png
EDIT
"requests that fire when a certain element events occur" - this is the key phrase, I think. Please provide some info on how you set your events. Maybe it fires twice because you have multiple handlers set? – Igor Zinov'yev
Ok, the thing is when I hit refresh the problem usually resolves itself, so not sure how that could be a handler issue, here's the event handler we typically use for a change of a select box.
$("#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:''
}
});
});
The problem I have is I have no idea how to replicate the problem, so I do not know if the event is being fired multiple times or whether the AJAX is requesting twice.
EDIT 2
If you are reloading the elements that are bound then the change events could be triggered recursively... We really need to see more code (what do you do on success of the ajax call etc) – redsquare
Thanks redsquare, upon a successful AJAX request I usually apply the response (usually HTML of <option>
s) to the target. I never trigger a change from the element that fired the AJAX, but I sometimes trigger a change on the target element, to allow for cascading AJAX requests. If this were the problem, surely this would happen all the time? My wrapper function uz_ajax
is below:
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
}
},
plete: function () {
/* if all ajax requests have pleted, 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
});
}
another way to stop multiple ajax requests is to heck jQuery.active prior to the call. jQuery keeps an internal count of 'live' ajax requests using this property. – redsquare
I'll look into this.
EDIT 3
So this is the result of the $('element').data(), but I can't understand what it's trying to say, does this mean there are two binds to it. If so how do I find out what these binds are and why do they both not fire when the event is fired.
alt text .png
EDIT 4
Here's another screenshot of the problem, this time in a different place in the system. The green arrow is the element thats triggers the three ajax requests, not in firebug how there's six, and that they pair up and share timestamps down to the millisecond?
The top three are the ones that have not pleted, the bottom three have return the correct result.
alt text .png
EDIT 5
The image below demonstrates what happens when a select box is changed, it fires three different ajax requests.
I've managed to do a bit more debugging and I can tell you the following:
- The problem occurs regardless of how many ajax requests the initial element calls
- The problem occurs regardless of what plugins are used
- This event is definitely only being fired once
- My uz_ajax wrapper function is only being fired once per target (see the firebug console, "Line 29: uz_ajax()".
- I've added
console.info
on each of the jquery$.ajax()
callbacks to see what's firing and when, notice how the only callback to fire isbeforeSend()
.
alt text .png
EDIT 6
Right then, after @redsquare suggested via Twitter about using console.trace()
to find out "where the second event is firing from" is, like I've always maintained I'm sure there isn't two events firing so I put the trace in the $.ajax()
method, here's what happened:
alt text .png
As you can see I get the duplicate ajax request problem even though the $.ajax()
method has only fired once, again the timestamps are identical. Have I e across a bug with jQuery?
EDIT 7
It happens on StackOverflow too!
alt text .png
Right then, I'm ing to the end of a rewrite of our JavaScript system, we're moving from Prototype to jQuery. We have a load of AJAX requests that fire when a certain element events occur, the one in the example below is a new event on a calendar, but it happens elsewhere too.
The problem I'm getting is when an event is fired sometimes two AJAX requests are made. The first one returns the correct value but (as you can see) it still says processing, it never returns the success message my JavaScript requires. The second request returns the correct result AND terminates correctly.
The problem I have is our jQuery screen blocker is set up to prevent user input during heavy AJAX requests, obviously because there an AJAX request still live the screen never unlocks. If I were to refresh this screen all will work as desired.
Can anyone shed any light on why this behavior is occuring.
alt text http://archive.ilmv.co.uk/images/jquery-duplicate-ajax-request.png
EDIT
"requests that fire when a certain element events occur" - this is the key phrase, I think. Please provide some info on how you set your events. Maybe it fires twice because you have multiple handlers set? – Igor Zinov'yev
Ok, the thing is when I hit refresh the problem usually resolves itself, so not sure how that could be a handler issue, here's the event handler we typically use for a change of a select box.
$("#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:''
}
});
});
The problem I have is I have no idea how to replicate the problem, so I do not know if the event is being fired multiple times or whether the AJAX is requesting twice.
EDIT 2
If you are reloading the elements that are bound then the change events could be triggered recursively... We really need to see more code (what do you do on success of the ajax call etc) – redsquare
Thanks redsquare, upon a successful AJAX request I usually apply the response (usually HTML of <option>
s) to the target. I never trigger a change from the element that fired the AJAX, but I sometimes trigger a change on the target element, to allow for cascading AJAX requests. If this were the problem, surely this would happen all the time? My wrapper function uz_ajax
is below:
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
}
},
plete: function () {
/* if all ajax requests have pleted, 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
});
}
another way to stop multiple ajax requests is to heck jQuery.active prior to the call. jQuery keeps an internal count of 'live' ajax requests using this property. – redsquare
I'll look into this.
EDIT 3
So this is the result of the $('element').data(), but I can't understand what it's trying to say, does this mean there are two binds to it. If so how do I find out what these binds are and why do they both not fire when the event is fired.
alt text http://archive.ilmv.co.uk/images/firebug-jquery-data-events.png
EDIT 4
Here's another screenshot of the problem, this time in a different place in the system. The green arrow is the element thats triggers the three ajax requests, not in firebug how there's six, and that they pair up and share timestamps down to the millisecond?
The top three are the ones that have not pleted, the bottom three have return the correct result.
alt text http://archive.ilmv.co.uk/images/jquery-duplicate-ajax-request-v2.png
EDIT 5
The image below demonstrates what happens when a select box is changed, it fires three different ajax requests.
I've managed to do a bit more debugging and I can tell you the following:
- The problem occurs regardless of how many ajax requests the initial element calls
- The problem occurs regardless of what plugins are used
- This event is definitely only being fired once
- My uz_ajax wrapper function is only being fired once per target (see the firebug console, "Line 29: uz_ajax()".
- I've added
console.info
on each of the jquery$.ajax()
callbacks to see what's firing and when, notice how the only callback to fire isbeforeSend()
.
alt text http://archive.ilmv.co.uk/images/jquery-duplicate-ajax-request-v3.png
EDIT 6
Right then, after @redsquare suggested via Twitter about using console.trace()
to find out "where the second event is firing from" is, like I've always maintained I'm sure there isn't two events firing so I put the trace in the $.ajax()
method, here's what happened:
alt text http://archive.ilmv.co.uk/images/jquery-duplicate-ajax-request-v4.png
As you can see I get the duplicate ajax request problem even though the $.ajax()
method has only fired once, again the timestamps are identical. Have I e across a bug with jQuery?
EDIT 7
It happens on StackOverflow too!
alt text http://archive.ilmv.co.uk/images/jquery-duplicate-ajax-request-v5.png
Share Improve this question edited Jul 7, 2010 at 8:26 Ben Everard asked Jul 1, 2010 at 8:26 Ben EverardBen Everard 13.8k14 gold badges69 silver badges96 bronze badges 36- 1 "requests that fire when a certain element events occur" - this is the key phrase, I think. Please provide some info on how you set your events. Maybe it fires twice because you have multiple handlers set? – Igor Zinov'yev Commented Jul 1, 2010 at 8:30
- I'll add some more information in the EDIT at the end. – Ben Everard Commented Jul 1, 2010 at 8:33
- If you are reloading the elements that are bound then the change events could be triggered recursively... We really need to see more code (what do you do on success of the ajax call etc) – redsquare Commented Jul 1, 2010 at 9:22
- another way to stop multiple ajax requests is to heck jQuery.active prior to the call. jQuery keeps an internal count of 'live' ajax requests using this property. – redsquare Commented Jul 1, 2010 at 9:27
- Cheers @redsquare, have another look at my question, I've responded under EDIT 2 :-) – Ben Everard Commented Jul 1, 2010 at 9:40
4 Answers
Reset to default 1Have you tried using a .click() instead? I have had issues with irregular activity using .change() in javascript. Give that a try.
Right, so I've e to a conclusion, I'm pretty sure that my problem is an issue with Firebug, as I've tested it the app on FF without Firebug turned on and it works as it should do.
This isn't the first time something JavaScript related has led me on a merry dance when the symptoms thrown by the problem don't offer any reasonable hint to the solution, but there we have it.
Massive thanks to @redsquare, who's helped massively both here, but via twitter and the jQuery IRC channel, many thanks dude!
Try to add return false
to your onchange function.
This will stop jQuery from bubbling the event.
You should make sure that $("#my_select","#context").change(function(){
is only called once.
I have tried this:
$(selector).unbind().on(eventname,function(){
$.ajax({
//ajax code here
});
});
It worked.
本文标签: javascriptjQuery AJAX problemsintermittently getting duplicate requestsStack Overflow
版权声明:本文标题:javascript - jQuery AJAX problems, intermittently getting duplicate requests - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744185692a2594280.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论