我正在尝试在IE上进行跨域。
我使用了XDomainRequest,并为所有事件(onerror,onload,onprogress和ontimeout)植入了日志记录来监控进度。
它有时可以工作,但并非总是如此(一台计算机,IE9,相同的站点,相同的请求,3或4个工作中的1个;另一台计算机,IE8,可能是2个工作中的1个)。我没有从日志记录中获得任何有用的信息,因为没有触发任何信息。
我很困惑。 IE的任何调试工具?为什么有些时候XDomainRequest不起作用?
非常感谢 冠蛋白
答案 0 :(得分:19)
XDomainRequest对象中至少存在两个重要错误,一个影响IE8,另一个影响IE9。
问题1 - 垃圾收集
在Internet Explorer 8中,调用send()但尚未完成后,XDomainRequest对象不正确地进行垃圾回收。这个bug的症状是开发人员工具'网络跟踪显示" Aborted"对于请求,并且不调用任何错误,超时或成功事件处理程序。
典型的AJAX代码看起来有点像这样:
function sendCrossDomainAjax(url, successCallback, errorCallback) {
var xdr = new XDomainRequest();
xdr.open("get", url);
xdr.onload = function() { successCallback(); }
xdr.onerror = function() { errorCallback(); }
xdr.send();
}
在此示例中,包含XDomainRequest的变量超出范围。如果用户不幸,IE的垃圾收集器将在send()异步完成之前运行,请求将被中止。即使可以将XDomainRequest对象捕获到OnLoad和OnError事件处理程序中,IE也会看到整个对象图没有引用它并将垃圾收集它。 IE应该是"固定"对象直到完成。
您会注意到互联网上的其他一些讨论,提到在xdr.send()周围放置一个setTimeout;电话将以某种方式解决"解决"神秘的XDomainRequest失败。这是一个kludge,完全不正确。所有这一切都发生在XDomainRequest对象被固定"进入setTimeout闭包并且不受垃圾收集的影响很快。它没有解决问题。
要正确解决此问题,请确保XDomainRequest存储在全局变量中,直到请求完成。例如:
var pendingXDR = [];
function removeXDR(xdr) {
// indexOf isn't always supported, you can also use jQuery.inArray()
var index = pendingXDR.indexOf(xdr);
if (index >= 0) {
pendingXDR.splice(index, 1);
}
}
function sendCrossDomainAjax(url, successCallback, errorCallback) {
var xdr = new XDomainRequest();
xdr.open("get", url);
xdr.onload = function() {
removeXDR(xdr);
successCallback();
}
xdr.onerror = function() {
removeXDR(xdr);
errorCallback();
}
xdr.send();
pendingXDR.push(xdr);
}
问题2 - 缺少OnProgress EventHandler
第二个问题已为人所知。 Internet Explorer 9在XDomainRequest对象中引入了回归,其中缺少(null)OnProgress事件处理程序会在请求尝试报告进度信息时导致请求中止。
对于快速请求,IE9从不尝试调用OnProgress事件处理程序并且请求成功。某些条件,例如由于过多的打开连接,网络延迟,服务器响应缓慢或大量请求或响应有效负载而导致IE延迟请求时,IE9将开始报告进度信息。
IE9尝试调用事件处理程序而不先检查它是否存在,并且XDomainRequest对象在内部崩溃并自行销毁。
要解决此问题,请始终确保将事件处理程序附加到OnProgress。鉴于该错误,在所有对象的事件中防御性地添加事件处理程序并不是一个坏主意。
var xdr = new XDomainRequest();
xdr.open("get", url);
xdr.onprogress = function() { };
// regsister other event handlers
其他问题
如果在调用.open()之前注册事件处理程序,我似乎有报告称XDomainRequest可能会失败。同样,在防守方面,在.open()和.send()调用之间注册它们并不是一个坏主意。我还没有亲自验证它是否是一个真正的错误。
如果遇到“拒绝访问”#34;错误,因为XDomainRequest不允许目标和主机页面之间的URI方案不匹配。换句话说,请尝试不要从HTTPS页面调用HTTP资源。
小心互联网上的大多数XDomainRequest库。我查看了大多数流行的插件,例如各种jQuery AJAX传输插件(包括在另一个答案中链接的插件)。
当然,XDomainRequest受其所有正常limitations and constraints的约束。这些不是本身的错误,并且与alernatives(iframe kludges,Flash crossdomain.xml传输)相比,它们 不好。
我在公共域名许可下发布了一个新的jQuery AJAX XDomainRequest传输:https://github.com/ebickle/snippets/tree/master/javascript/xdomainrequest
答案 1 :(得分:11)
有完全相同的问题。简短的解决方案:
更新:链接已损坏,请在此处找到jaubourgs:https://github.com/jaubourg/ajaxHooks/blob/master/src/xdr.js
xdr.onprogress = function() {};
详细信息可以在这里的jQuery主题讨论中找到
http://bugs.jquery.com/ticket/8283
其中最后一个回复包含xdr.onprogress修复,该修复源于此错误讨论,该讨论恰当地标题为
“IE9 RTM - 如果未指定所有事件处理程序,XDomainRequest发出的请求可能会中止” http://social.msdn.microsoft.com/Forums/en-US/iewebdevelopment/thread/30ef3add-767c-4436-b8a9-f1ca19b4812e