本文介绍了IE、XDomainRequest 并不总是有效的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在 IE 上进行跨域.

I am trying to do cross-domain on IE.

我使用 XDomainRequest,并为所有事件(onerror、onload、onprogress 和 ontimeout)植入日志来监控进度.

I used XDomainRequest, and implanted logging for all events (onerror, onload, onprogress and ontimeout) to monitor the progress.

它有时会起作用,但并非总是如此(一台计算机,IE9,同一站点,相同的请求,3 或 4 个工作中的 1 个;另一台计算机,IE8,也许 2 个工作中的 1 个).我没有从日志中得到任何有用的信息,因为没有触发任何东西.

It works sometime, but not always (one computer, IE9, same site, same request, 1 out of 3 or 4 works; another computer, IE8, maybe 1 out of 2 works). I didn't get any useful information from the logging, because there was nothing triggered.

我很困惑.IE 有什么调试工具吗?为什么有时 XDomainRequest 不起作用?

I am very confused. Any debugging tool for IE? Why some time XDomainRequest just doesn't work?

非常感谢花冠素

推荐答案

XDomainRequest 对象中至少有两个重大错误,一个影响 IE8,另一个影响 IE9.

There are at least two significant bugs in the XDomainRequest object, one that affects IE8 and another that affects IE9.

问题 1 - 垃圾收集

在 Internet Explorer 8 中,XDomainRequest 对象在 send() 已被调用但尚未完成后被错误地进行垃圾回收.此错误的症状是开发人员工具的网络跟踪显示请求中止",并且没有调用任何错误、超时或成功事件处理程序.

In Internet Explorer 8, the XDomainRequest object is incorrectly subject to garbage collection after send() has been called but not yet completed. The symptoms of this bug are the Developer Tools' network trace showing "Aborted" for the requests and none of the error, timeout, or success event handlers being called.

典型的 AJAX 代码看起来有点像这样:

Typical AJAX code looks a bit like this:

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 的 Javascript 垃圾收集器将在 send() 异步完成之前运行,并且请求将被中止.即使 XDomainRequest 对象可以被捕获到 OnLoad 和 OnError 事件处理程序中,IE 也会看到整个对象图没有对它的引用,并将对其进行垃圾收集.IE 应该固定"对象直到完成.

In this example, the variable containing XDomainRequest goes out of scope. If the user is unlucky, IE's Javascript garbage collector will run before send() asynchronously completes and the request will be aborted. Even though the XDomainRequest object can be captured into the OnLoad and OnError event handlers, IE will see that that entire object graph has no references to it and will garbage collect it. IE should be "pinning" the object until complete.

您会注意到互联网上有很多其他讨论提到在 xdr.send(); 周围放置 setTimeout;call 会以某种方式解决"神秘的 XDomainRequest 失败.这是胡说八道,完全不正确.发生的所有事情是 XDomainRequest 对象被固定"到 setTimeout 闭包中,并且不会很快受到垃圾收集的影响.它不能解决问题.

You'll notice quite a few other discussions on the internet mentioning that placing a setTimeout around the xdr.send(); call will somehow "solve" mysterious XDomainRequest failures. This is a kludge, and completely incorrect. All that's happening is that the XDomainRequest object is being "pinned" into the setTimeout closure and not subject to garbage collection as quickly. It doesn't solve the problem.

要正确解决此问题,请确保 XDomainRequest 存储在全局变量中,直到请求完成.例如:

To correctly work around this issue, ensure the XDomainRequest is stored in a global variable until the request completes. For example:

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 对象中引入了回归,其中缺少(空)OnProgress 事件处理程序会导致请求在尝试报告进度信息时中止.

This second issue is already known. Internet Explorer 9 introduced a regression in the XDomainRequest object where a missing (null) OnProgress event handler would cause the request to abort when it tries to report progress information.

对于快速请求,IE9 从不尝试调用 OnProgress 事件处理程序并且请求成功.某些情况下,例如当 IE 因打开连接过多、网络延迟、服务器响应缓慢或请求或响应负载较大而延迟请求时,会导致 IE9 开始报告进度信息.

For fast requests, IE9 never attempts to call the OnProgress event handler and the request succeeds. Certain conditions, such as when IE delays the request due to too many open connections, network latency, slow server responses, or large request or response payloads will cause IE9 to start to report progress information.

IE9 尝试调用事件处理程序而不先检查它是否存在,并且 XDomainRequest 对象崩溃并在内部销毁自身.

IE9 tries to call the event handler without first checking it exists, and the XDomainRequest object crashes and destroys itself internally.

要解决此问题,请始终确保将事件处理程序附加到 OnProgress.鉴于此错误,将事件处理程序防御性地添加到对象的所有事件中并不是一个坏主意.

To solve this issue, always ensure an event handler is attached to OnProgress. Given the bug, it's not a bad idea to defensively add event handlers to all of the object's events.

var xdr = new XDomainRequest();
xdr.open("get", url);
xdr.onprogress = function() { };
// regsister other event handlers

其他问题

我似乎报告说,如果在调用 .open() 之前注册了事件处理程序,则 XDomainRequest 可能会失败.再次,防御性地,在 .open() 和 .send() 调用之间注册它们并不是一个坏主意.我还没有亲自验证它是否是一个真正的错误.

I've seem reports that XDomainRequest can fail if the event handlers are registered before .open() is called. Again, defensively, it's not a bad idea to register them between the .open() and .send() calls. I haven't personally verified whether it's an actual bug.

如果您遇到拒绝访问"错误,那是因为 XDomainRequest 不允许目标页面和主机页面之间存在不匹配的 URI 方案.换句话说,尽量不要从 HTTPS 页面调用 HTTP 资源.

If you run into an "Access Denied" error, it's because XDomainRequest doesn't allow mismatched URI schemes between the target and host page. In other words, try don't call an HTTP resource from an HTTPS page.

当心互联网上的大多数 XDomainRequest 库.我查看了大多数流行的插件,例如各种 jQuery AJAX 传输插件(包括此处另一个答案中链接的插件).

Beware most of the XDomainRequest libraries on the internet. I looked at most of the popular ones, such as the various jQuery AJAX transport plugins (including the ones linked in another answer here).

当然,XDomainRequest 受制于所有正常的限制和约束.这些本身并不是错误,与替代方案(iframe kludges、Flash crossdomain.xml 传输)相比,它们还不错.

And, of course, XDomainRequest is subject to all of it's normal limitations and constraints. These aren't bugs per-se, and compared with the alernatives (iframe kludges, Flash crossdomain.xml transports) they're not that bad.

我在公共域许可下发布了一个新的 jQuery AJAX XDomainRequest 传输:https://github.com/ebickle/snippets/tree/master/javascript/xdomainrequest

I've posted a new jQuery AJAX XDomainRequest transport under a public domain license here: https://github.com/ebickle/snippets/tree/master/javascript/xdomainrequest

这篇关于IE、XDomainRequest 并不总是有效的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-05 13:11