XMLHttpRequest Object Has An Abort() Method

Posted October 19, 2007 at 4:21 PM by Ben Nadel

Tags: Javascript / DHTML

I made an update to the my Kinky File Explorer this morning to fix the bug involving the asynchronous behavior of the AJAX file loading. The problem was that if you clicked around the file tree fast, the code that you ended up with on the right hand side might not reflect the file tree selection. This was due to the fact that the order of AJAX callback handler executions was not tied directly to the order of the file tree selections (hence the asynchronous nature).

Last night, when reading up on jQuery, I actually happened upon the key to a solution: the XMLHttpRequest .abort() method. I have not done a ton with AJAX so this method was unknown to me, but basically what it does is cancel the currently executing AJAX request tied to the given XMLHttpRequest Object and ensures that the call back handler does not get executed (assuming it has not returned yet).

So now, as part of my Kinky File Explorer data file loading, I have a global variable that keeps track of the currently executing file request. If a new file request has been launched before the previous one has finished executing, the Javascript will .abort() the previous request and store the new request into the global variable. This way, I only ever have one AJAX request taking place at a time which is perfect because I only ever want the most recent file tree selection to be loaded into the "code" content area.

Here is what that part of the now looks like:

  • // This will load the given file into the PRE element.
  • function ShowFile( strPath ){
  •  
  • // Check to see if there is an AJAX request already in
  • // progress that needs to be stopped.
  • if (objHttpFileDataRequest){
  •  
  • // Abort the AJAX request.
  • objHttpFileDataRequest.abort();
  •  
  • }
  •  
  • // Use AJAX to get the text of the file and store the
  • // new AJAX request object into the global variable.
  • objHttpFileDataRequest = $.get(
  • "index.cfm",
  • {
  • getdata: 1,
  • file: encodeURI( strPath )
  • },
  • function( strFileData ){
  • $( "pre#fileoutput" ).text( strFileData );
  • }
  • );
  •  
  • }
  •  
  •  
  • // Store a global value to the HTTP request object that is
  • // going to be used in our AJAX file data calls. In order
  • // to make sure that calls are not jumbled, we want to
  • // serialize our requests. Meaning, if one request goes out,
  • // it should abort any previously running request.
  • var objHttpFileDataRequest = null;

Now, granted, I probably don't need to call .abort() on AJAX requests that have already finished executing, but for simplicity's sake, I am calling .abort() if the XMLHttpRequest object exists, regardless. jQuery makes this code wicked simple and I am seeing now that jQuery provides some additional AJAX utility methods that will make these kinds of situations even easier to deal with (ex. $.ajaxStart(), $.ajaxStop()).



Reader Comments

Oct 19, 2007 at 5:59 PM // reply »
153 Comments

Given that you appear to be using GET requests (I know nothing of jQuery, but I assume $.get means GET), and that you don't appear to be doing any cache-busting, may I suggest something else?

Instead of storing whatever the current one is, and throwing away anything else, why not just check the result against the current one, and only apply the change if it is the right one? That is:

/* Outside the function */
var strCurrentFetchingFile = '';
/* Later, inside the function */
strCurrentFetchingFile = strPath;
$.get("index.cfm",{getdata: 1,file: encodeURI(strPath)},
function(strFileData) {
if(strPath == strCurrentFetchingFile) {
$("pre#fileoutput").text(strFileData);
strCurrentFetchingFile = null;
}
}
);

Using abort() seems a bit heavy-handed to me. The call has already been made, and less you have a really smart server script that can detect dropped connections, the script is going to process to completion anyway. But, if you abort, then likely the browser will just have to make that same call later again, possibly fetching much of the same content. Instead, let the browser complete the call and put it in its cache. Just don't act on it if it isn't the data you want to see.

Of course, if you later decide to add expiry to the content and want to same some bandwidth, the abort() option may be the best bet.


Oct 19, 2007 at 6:13 PM // reply »
11,314 Comments

@Rick,

That's a pretty clever idea. I didn't think of any caching issues / benefits, but that's not a bad tip at all :) Thanks a lot.


Jul 6, 2008 at 4:34 PM // reply »
1 Comments

I've been using the jQuery higher level .load(url) method rather than .get. I'm wondering if there's still a way to get access to the XMLHttpRequest object in order to abort the request, or whether I have to abandon the load method to do that. Thanks!


Jul 7, 2008 at 8:41 AM // reply »
11,314 Comments

@Ruby,

It looks like the request object gets passed back through to the call back, but by then, I guess it is too late to abort a request.


Jun 23, 2010 at 7:30 AM // reply »
2 Comments

I came across this post while searching for information on what jQuery does with the success callback function on an aborted request. I understand this is an old post, but it might be worth mentioning that this will not work using jQuery 1.4.2. The change is that the success function will always be fired when aborting a xhr. You will need to check the xhr.status in the success function to handle aborted requests. Please see Mr Resig's reponse to this: http://is.gd/d0nvo


Jun 23, 2010 at 10:51 AM // reply »
11,314 Comments

@Richard,

Very interesting! I had no idea that aborting a request might call any of the callback handlers (success OR complete). I'll have to do some looking into that. Thanks for the tip off.


Jun 23, 2010 at 11:01 AM // reply »
2 Comments

@Ben

Cool beans. Yea it's a bit of a pain! One would think none of the callback handlers would be executed on an aborted request. I'm sure there's good reasoning for the change. (This was not the default behaviour in jQuery 1.3.2)


Jan 17, 2011 at 3:48 PM // reply »
1 Comments

Works very well. I revamped some javascript code into the jquery method and even though it essentially does the same thing as it used to, its about half the code length and allows for easy use of the abort function which is a godsend :) Thanks!


Mar 11, 2012 at 11:49 PM // reply »
1 Comments

Nice Ben ! I've just found your post while googling. Even if it is an old post, what you explained helpt me about an issue with callbacks handlers.
But do you have any other useful informations regards to the server side ? I read that even if you abort / cancel the request, it was still proceeded by the server, which doesn't really help.
Any feedbacks are welcome. Cheers ! !


May 5, 2012 at 1:49 PM // reply »
1 Comments

There was an infinite loop in a PHP script, calling abort() method will just kill Ajax request on client side, I had to reboot Apache server :D


Post A Comment

Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.

Please review the following issues:

Author Name:


Author Email:

Author Website:

Comment:

Supported HTML tags for formatting: <strong>bold</strong>   <em>italic</em>   <code>code</code>







  • Help Wanted - Find Your Next ColdFusion Job
Ben Nadel's Company - Epicenter Consulting Recent Blog Comments
Jun 19, 2013 at 11:33 AM
Filter vs. ngHide With ngRepeat In AngularJS
In your assessment, is it correct to say that given a list of say 500 items its more performant to use the `ngHide` method over the `filter` method? ... read »
Jun 19, 2013 at 10:18 AM
ColdFusion Path Usage And Manipulation Overview
Anyone happen to know if the file created by getTempFile will be automatically removed at any point? Nothing mentioned in the docs, and restarting CF doesn't remove them, so it seems it needs manu ... read »
Jun 19, 2013 at 9:41 AM
Working With Inherited Collections In AngularJS
I actually just ran into this same situation with a demo I was putting together. Your implementation of multi-lvl $scope's > Mine :) ... read »
Jun 19, 2013 at 8:17 AM
My Experience With AngularJS - The Super-heroic JavaScript MVW Framework
@Prateek, to match a word or text you should use .toContain('word') that's a jasmine reference. website is : http://pivotal.github.io/jasmine/ ... read »
Jun 19, 2013 at 8:10 AM
My Experience With AngularJS - The Super-heroic JavaScript MVW Framework
Hi Guys, Actually i am doing e2e test of angular js of my project but i am not getting one thing that is how to press enter key through the test when my form is filled as i am not using a button but ... read »
Jun 18, 2013 at 9:20 PM
Mapping AngularJS Routes Onto URL Parameters And Client-Side Events
I couldn't find examples of passing multiple arguments using the when() routing statement so figured out through trial and error that you can pass multiple arguments using the following format: .whe ... read »
Jun 18, 2013 at 3:39 PM
Experimenting With The Amazon Simple Storage Service (S3) API Using ColdFusion
Hi Ben, THANKS! While not bleeding edge, it is new to me & I like learning new things every day! ... read »
Jun 18, 2013 at 12:30 PM
Disabling Auto-Correct And Auto-Capitalize Features On iPhone Inputs
Also spellcheck="false" should be mentioned as part of html5 specs ... read »
InVision App - Prototyping Made Beautiful With Prototyping Tools