1

I have two jsbin's illustrating the code:

http://jsbin.com/OdiSApI/1/edit This will hit an alert in IE8 - this alert is in a calling function, ExecuteSearch.

http://jsbin.com/OdiSApI/2/edit This seems to work fine in IE8.

Note: You'll need to click the Run with JS button in the top right pane. Then enter a city in the text field that's within the dropdown state and submit the form (this calls google maps geocode API).

The "fix" in the 2nd link is the following:

//account for asynchronous nature of IE XDR request
//geo_location is undefined here in IE8
//this seems to fix ie8, though I'm not sure why...
var timeout = setTimeout(function() {
    clearTimeout(timeout);
}, 10);

The problem I was having is I'm having to use a XDomainRequest (XDR) for IE8-9 (partial CORS support). In the first jsbin, I'm hitting the alert in my ExecuteSearch function because my GeoCode function is returning before my xdr.onload is firing.

The timeout seems to be queueing my asynchronous XDR, though I'm not really sure what is happening and why that timeout seems to be my magic bullet here.

Anyone have any ideas?

magenta placenta
  • 1,461
  • 7
  • 22
  • 34
  • It merely looks like *asynchronous programming is not being used*. Any such *gross hacks* don't fix the fundamental problem and will vary by browser, if they do anything. You can't "return geo_location" *before* (in terms of program execution timeline) the XDR callback! I recommend merely returning a Promise/A ($.ajax returns one, XDR for IE can be wrapped) and then correctly using asynchronous (i.e. callback) programming. – user2246674 Sep 03 '13 at 21:37
  • That being said, it would be *slightly* interesting to see into the IE8 implementation and why such a dummy timeout would make it work. Note that `XDR.send` is only guaranteed synchronous insofar as the data is "sent", not that is returned (i.e. onload is invoked only *after* the complete response is received). Thus, as with my previous comment: I recommend Promises/A and moving on using an asynchronous model (so also remove `async: false` from the normal AJAX). – user2246674 Sep 03 '13 at 21:41
  • Asynchronous programming is definitely being used. setTimeout is increasing the amount of time between open() and send(). Since the XDR object is being captured into the setTimeout closure, it's kept safe from the garbage collector longer. If it takes awhile for the HTTP connection to be established, send() will take longer because it needs to wait for open() to complete asynchronously. While send() is executing, XDR has gone out of scope and can be garbage collected. The setTimeout keeps the XDR object around longer, making it more likely that open() will complete before send(). – ShadowChaser Dec 20 '14 at 19:19

1 Answers1

1

setTimeout isn't fixing the issue.

What's actually occuring is that IE8 has a bug in the XDomainRequest object where it's subject to garbage collection while a pending request is open.

If you take a look at your original source code, the "xdr" variable is going out of scope immediately after send() is called. This shouldn't be a bug, but IE8 is noticing the variable is now never referenced from anywhere. If you're unlucky, the garbage collector will run before send() asynchronously completes and nukes the object out from under you.

The reason setTimeout appears to work is because it's keeping the XDR object in scope for slightly longer. It appears to work but in reality doesn't solve the issue - the race condition still exists and if the garbage collector runs later it can still destroy the XDomainRequest object.

I posted some detailed information about the various XDomainRequest issues, with workarounds, here: IE, XDomainRequest not always work

Community
  • 1
  • 1
ShadowChaser
  • 5,520
  • 2
  • 31
  • 33