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:
Launch code in new window » Download code as text file »
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()).
Download Code Snippet ZIP File
Comments (2) | Post Comment | Ask Ben | Permalink | Other Searches | Print Page
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.
Posted by Rick O on Oct 19, 2007 at 5:59 PM
@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.
Posted by Ben Nadel on Oct 19, 2007 at 6:13 PM