【问题标题】:Not understanding how/why this setTimeout is fixing my IE8 issue不明白这个 setTimeout 如何/为什么解决我的 IE8 问题
【发布时间】:2013-09-07 06:06:31
【问题描述】:

我有两个 jsbin 的代码说明:

http://jsbin.com/OdiSApI/1/edit 这将在 IE8 中触发警报 - 此警报在调用函数 ExecuteSearch 中。

http://jsbin.com/OdiSApI/2/edit 这似乎在 IE8 中运行良好。

注意:您需要点击右上角窗格中的Run with JS按钮。然后在下拉状态中的文本字段中输入一个城市并提交表单(这会调用 google maps geocode API)。

第二个链接中的“修复”如下:

//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);

我遇到的问题是我不得不为 IE8-9 使用 XDomainRequest (XDR)(部分 CORS 支持)。在第一个 jsbin 中,我在 ExecuteSearch 函数中触发了警报,因为我的 GeoCode 函数在 xdr.onload 触发之前返回。

超时似乎在排队我的异步 XDR,但我不确定发生了什么以及为什么超时似乎是我的灵丹妙药。

有人有什么想法吗?

【问题讨论】:

  • 看起来只是没有使用异步编程。任何这样的严重的黑客攻击都不能解决根本问题,并且会因浏览器而异,如果他们做任何事情的话。您不能(就程序执行时间线而言)XDR 回调之前“返回 geo_location”!我建议只返回一个 Promise/A($.ajax 返回一个,可以包装 IE 的 XDR),然后正确使用异步(即回调)编程。
  • 话虽如此,了解 IE8 实现以及为什么这样的虚拟超时会使其工作会有点有趣。请注意,XDR.send 仅在数据“发送”时保证同步,而不是返回数据(即仅在收到完整响应后调用 onload)。因此,与我之前的评论一样:我推荐 Promises/A 并继续使用异步模型(因此还要从普通 AJAX 中删除 async: false)。
  • 肯定在使用异步编程。 setTimeout 增加了 open() 和 send() 之间的时间。由于 XDR 对象被捕获到 setTimeout 闭包中,因此它可以更长时间地远离垃圾收集器。如果建立 HTTP 连接需要一段时间,send() 将需要更长的时间,因为它需要等待 open() 异步完成。当 send() 正在执行时,XDR 已经超出范围并且可以被垃圾收集。 setTimeout 使 XDR 对象保持更长的时间,使得 open() 更有可能在 send() 之前完成。

标签: javascript asynchronous internet-explorer-8 queue settimeout


【解决方案1】:

setTimeout 不能解决问题。

实际发生的情况是 IE8 在 XDomainRequest 对象中存在一个错误,在该对象中,当挂起的请求打开时,它会受到垃圾回收的影响。

如果您查看原始源代码,“xdr”变量会在调用 send() 后立即超出范围。这不应该是一个错误,但 IE8 注意到该变量现在从未从任何地方引用。如果你不走运,垃圾收集器会在 send() 异步完成之前运行,并将对象从你下面删除。

setTimeout 似乎起作用的原因是因为它使 XDR 对象在范围内的时间稍长一些。它似乎有效,但实际上并不能解决问题 - 竞争条件仍然存在,如果垃圾收集器稍后运行,它仍然可以破坏 XDomainRequest 对象。

我在此处发布了有关各种 XDomainRequest 问题的一些详细信息以及解决方法:IE, XDomainRequest not always work

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-11-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-17
    • 2014-04-11
    • 2015-06-13
    相关资源
    最近更新 更多