flXHR and chained Ajax calls
The actual reason has to do with synchronicity of single-execution-threads in Javascript (see, I told you that you didn’t want to know the gory details!). While the response handler for Ajax call #1 is executing, the flXHR instance it’s dealing with is already in readyState=4, which means it’s available for reuse according to flXHR’s feature internals. So, when you make a call from that handler to get a new flXHR instance, it will simply reconfigure and return you (actually, directly to the internals of the framework Ajax calling logic) the existing flXHR instance you were already dealing with.
This sounds fine, right? It’s all great except for the fact that *after* a framework synchronously calls the handler function (in which you fire off a new Ajax request), it then sometimes will try to “cleanup” after itself (in actuality, usually a good thing!). But, now the original Ajax execution thread code, and the second fired off Ajax call thread, are dealing with references to the same flXHR instance. And so, the cleanup code can come along and zero out handler assignments to the shared instance (thinking it’s doing so against a throw-away instance), which causes the chained secondary Ajax call to misbehave (specifically, to appear to be abandoned).
So, again, this is a race condition. And unfortunately, due to the way that both flXHR and the framwork Ajax calls work, neither of us can fix that unfortuate catch-22. So, how does one do chained Ajax with flXHR and instancePooling? I’m glad you asked!
The answer is actually pretty simple. It involves what would normally be considered a fairly complex Javascript topic, but one which tends to creep in as a solution for lots of different types of Javascript race conditions. So, if you can just accept that pattern I present here, and not try to understand much of the whys, you should be fine. Or you can get your Ph.D. in Javascript and then you should be fine too!
What we need to do is this: while inside the response handler for Ajax call #1, surrender our chained Ajax call making code to not be in the same execution thread (synchronous), but in a subsequent (asynchronous) execution thread. This fancy mumbo jumbo will take care of allowing the existing framework cleanup code to finish its job on the shared flXHR instance, and *then* the new Ajax call will get the shared instance and run with it. Sounds simple right? It is, trust me.
Take a look at some common code which suffers this race condition bug:
function handleRequest_2(data,status) {
// do something with 2nd request data -- will fail to get called right now, in most circumstances
}
function handleRequest_1(data,status) {
// do something with the data response
...
// make another request
jQuery.ajax({url:"http://...", success:handleRequest_2, ...});
}
jQuery(document).ready(function(){
// set up jQuery to use flXHR -- old school way, see jQuery plugin for better!
jQuery.ajaxSetup({xhr:function() { return new flensed.flXHR({instancePooling:true,autoUpdatePlayer:true}); }});
// make the first request on page load
jQuery.ajax({url:"http://...", success:handleRequest_1, ... });
});
// rest of your code
See how the problem exists? While “handleRequest_1″ is running, it tells jQuery to run another Ajax call, using the same shared flXHR instance, so the assignment of “handleRequest_2″ as the success handler will get undone by the cleanup code that happens when “_1()” finishes.
Corrected code:
function handleRequest_1(data,status) {
// do something with the data response
...
// make another request, but do so asynchronously after current execution thread ends
setTimeout(function(){
jQuery.ajax({url:"http://...", success:handleRequest_2, ...});
},0);
}
// rest of your code
You see, the simple fix is to wrap your chained Ajax calling code in a setTimeout with an interval of 0ms. This will effectively cause that code to execute 0ms from now, which is at the very end of the current execution thread (including any cleanup code the framework may do). This will allow the second Ajax call to happen after the cleanup, so there should be no race condition.
Make sense? I hope so. Just follow that simple pattern of wrapping chained Ajax code in a setTimeout(…,0) and you should be fine!
Pages: 1 2
Comments (0)