Inconsistent ajax (XDR) response from IE
I'm making an ajax request from an iframe that is injected onto every page via an IE plugin. I'm using IE's cross domain request because jQuery's ajax fails for IE. This works 75% of the time on IE8 & 9. The other 25%, the xdr.onload
doesn't even fire.
The server php is doing its job...the log looks identical for when onload
does and does not fire. Also, xdr.onerror
doesn't fire either.
Any ideas?
thisURL = "http://example.com/getmsg.php?cmd=getMessage&iid=ddeb2c1228&uurl=http%3A%2F%2Fwww.cnn.com%2F&t=" + Math.random();
// Use Microsoft XDR
var xdr = new XDomainRequest();
xdr.open("GET", thisURL);
xdr.onload = function() {
// this is sometimes called, sometimes not in IE
alert('INCONSISTENT ALERT');
开发者_如何转开发 callback(xdr.responseText);
};
xdr.send();
I was having a very similar problem: XDomainRequests failing only some of the time, despite Fiddler showing all request and response headers being sent exactly as I intended. I had defined every event handler and the timeout property on these XDR objects, and none of the handlers were being called. The F12 developer tools showed the requests as aborted. Both GETs and POSTs could be aborted, to multiple different domains, but the first request always worked successfully.
Then I tried putting the calls to xdr.send
in a timeout, like this:
setTimeout(function () {
xdr.send();
}, 0);
and it worked. I have no idea why, but maybe this will be helpful to someone else.
You're correct in naming the title here. The experience is rather inconsistent. Let's walk through it...
var xdr, err, res, foo, url;
xdr = new XDomainRequest();
err = function(){ alert("There was an error, operation aborted"); }
res = function(){ alert("Success! " + xdr.responseText); }
foo = function(){ return; }
url = "http://hello.com/here/is/the/url/?query=true&whatever=asd";
xdr.onerror = err;
xdr.ontimeout = foo;
xdr.onprogress = foo;
xdr.onload = res;
xdr.timeout = 5000;
xdr.open("get", url);
xdr.send(null);
The XDomainRequest object handles differently in every IE.
In IE9 -> the XDomainRequest object requires that all handles are given a method. Meaning, that handles like onerror, onload, ontimeout, and onprogress are all given something to do. Without defining a method for these handles then you'll get a network response of "operation aborted".
In IE7/8/9 -> the XDomainRequest is ASYNC by default. It will execute the code further down the stack regardless of the xdr object completing or not. Putting a setTimeout may be a solution but shouldnt be.
In this case, trigger an event and listen for the event before executing any further code. An example of this would be (in jquery)...
// call this method in xdr onload
$(document).trigger("xdr_complete");
// use this wrapper in code you want to execute after the complete of xdr
$(document).bind("xdr_complete", function(){ ... });
In IE7/IE8 you'll notice it working. IE7 and IE8 are rather "loose" in that they don't abort when there are missing method for the handles.
Found out the issue last minute. In my case I needed to specify a timeout value, even though the requests were not timing out. In order to properly debug an XDR issue I'd suggest the following code, with each alert telling you what's going on with your code. As I said, in my case it was a missing timeout
declaration. But the code below should debug any XDR problems:
var xdr = new XDomainRequest();
if (xdr) {
xdr.onerror = function () {
// alert('xdr onerror');
};
xdr.ontimeout = function () {
// alert('xdr ontimeout');
};
xdr.onprogress = function () {
// alert("XDR onprogress");
// alert("Got: " + xdr.responseText);
};
xdr.onload = function() {
// alert('onload' + xdr.responseText);
callback(xdr.responseText);
};
xdr.timeout = 5000;
xdr.open("get", thisURL);
xdr.send();
} else {
// alert('failed to create xdr');
}
It is tough to give you a definitive answer here.
First, you should try using Fiddler to see if you are getting a network failure of some sort. It will help you to understand if the request has actually been made and the response from the server.
Second, and I don't know if this applies, we recently had a problem with cross domain on IE. The code worked fine in other browsers - Firefox, Safari and Chrome. The problem in that case turned out that the request was returning a 404 which was expected. Regardless, IE stopped all execution at that point, even our error handling of the 404 event was never fired. So, you could be getting some of the same here. Firefox, Safari, etc all let the script continue. If you are returning an error, you might want to have it return a success with an error value instead.
- First off, add an onerror handler to debug your stuff. Log them and see what exactly happens.
- Second, your 'math.random' approach is flawed. A better option is to use new Date().getTime(), this will ensure you have a unique requests as time passes by.
- Third, you could (probably should) use POST methods to bypass IE's obviously standards based behavior ( ;-) )
精彩评论