I was surprised to see that the prototype.js library does not include an abort method for its Ajax.Request object. So, here's my implementation of Ajax.Request.abort():
/**
* Ajax.Request.abort
* extend the prototype.js Ajax.Request object so that it supports an abort method
*/
Ajax.Request.prototype.abort = function() {
// prevent and state change callbacks from being issued
this.transport.onreadystatechange = Prototype.emptyFunction;
// abort the XHR
this.transport.abort();
// update the request counter
Ajax.activeRequestCount--;
};
To use this function, you need to keep a handle on the Ajax request you want to abort. So, somewhere in you code you'll have something like:
var myAjaxRequest = new Ajax.Request(requestUrl, {[request options]});
If you want to abort that request, simply call:
myAjaxRequest.abort();
Update - Feb. 22, 2008:
It was pointed out in the comments that the
Ajax.activeRequestCount
can occasionally become negative. I have been able to replicate that situation, while at the same time confirming that it does not consistently happen. This leads me to believe that it's most likely a timing issue such as the abort
is issued after the response has already started to be received and/or processed so that both the response processing decrements the counter as well as the abort.My personal work-around for this is to add these lines to the end of my
onComplete
handler:
if (Ajax.activeRequestCount < 0) {
Ajax.activeRequestCount = 0;
}
I don't want to remove the counter decrement from the
abort
function or else cleanly aborted requests will leave the activeRequestCount > 0 when there are no real outstanding requests.If anyone has a better solution, I'd be interested to hear from you.
Cheers mate.
ReplyDeleteThis sseems to have resolved an issue I was having when only calling: this.transport.abort();
Maybe you can shed some light on why the absence of the first line was preventing a concurrent Element.update() from executing?
Cheers mate.
ReplyDeleteThis sseems to have resolved an issue I was having when only calling: this.transport.abort();
Maybe you can shed some light on why the absence of the first line was preventing a concurrent Element.update() from executing?
Great article and thanks to Steven for helping me implement it!
ReplyDeleteThis should really be included in the official prototype.js.
Thanks so much Steve. Please excuse my newbieness. How do i integrate your abort code with my javascript module? Do I paste it in prototype.js or in my own module?
ReplyDeleteThanks so much
I would recommend that you just add it to your own JavaScript code sometime after you've included the prototype.js code.
ReplyDeleteI would not recommend you adding to the prototype.js file (or any other 3rd party library) as it then complicates the process of upgrading to new versions since you need to remember to copy over all the additions you have made.
Hi,
ReplyDeleteThanks for the code first of all.
I seem to have some issue with Ajax.activeRequestCount when using it in conjunction with Ajax.Responders. The activeRequestCount became negative. I commented out the "activeRequestCount--" line and it now seems fine.
Here is my code for the responders:
Ajax.Responders.register({
onCreate: function() {
//alert("# of request is "+Ajax.activeRequestCount);
if($('indicator1') && Ajax.activeRequestCount>0)
$('indicator1').show();
},
onComplete: function() {
if($('indicator1') && Ajax.activeRequestCount==0)
$('indicator1').hide();
},
onUninitialized: function() {
if($('indicator1') && Ajax.activeRequestCount==0)
$('indicator1').hide();
}
});
Hi,
ReplyDeleteFirst of all thanks.
I seem to get negative Ajax.activeRequestCount when using the code in conjunction with Ajax.Responders. I commented out the line "Ajax.activeRequestCount--;" and now it seems fine. Here is my code if that matters at all:
Ajax.Responders.register({
onCreate: function() {
//alert("# of request is "+Ajax.activeRequestCount);
if($('indicator1') && Ajax.activeRequestCount>0)
$('indicator1').show();
},
onComplete: function() {
if($('indicator1') && Ajax.activeRequestCount==0)
$('indicator1').hide();
},
onUninitialized: function() {
if($('indicator1') && Ajax.activeRequestCount==0)
$('indicator1').hide();
}
});
I use essentially the same code and have not encountered any issues with negative values.
ReplyDeleteAre you aborting a request that has already completed? In my response handling functions, I always set my saved Ajax object to null, and check the object before calling abort in it.
Thanks you verymuch. This is very usefull for me.
ReplyDeleteIts very likely that this hasn't been included in prototype because the abort method in XHR isn't supported by IE<7. Great addition though and when combined with a little object detection there's no reason it cant be implemented as a progressive enhancement
ReplyDeleteI'm using firefox and tried your solution on my project. When I abort ajax request code seems to work fine and nothing is done after aborting, but my firebug still shows there's a request running and it won't never stop. Is this only firebug's problem? I don't know but I decided to ask you if you have any knowledge about this.
ReplyDeleteThanks for posting this. I have been looking for something like this for a long time. I too was surprised not to find built in support as a part of Prototype's AJAX library.
ReplyDeleteHey are you a professional journalist? This article is very well written, as compared to most other blogs i saw today….
ReplyDeleteanyhow thanks for the good read!
Excellent article! I don't understand what are waiting Prototype to include this change on their code.
ReplyDeleteAbout the abort problem in some situations where the Ajax.activeRequestCount becomes negative and to avoid future problems when updating prototype as it was commented before, I did the following:
a) create a prototype_extended.js file and include it after including prototype.js to take effect.
b) put the following code:
Ajax.Responders.register({
onComplete: function(){
//alert ('inside oncomplete code section...');
Ajax.activeRequestCount--;
if (Ajax.activeRequestCount < 0) {
Ajax.activeRequestCount = 0;
}
}
});