调用同步XMLHttpRequest时,IE会挂起5分钟

8
我有一个Web应用程序,使用ajax调用我的Web服务器来获取数据。
有时(在不可预测的时刻,但可以重现),IE会完全挂起5分钟(窗口显示未响应),然后回来,xmlhttprequest对象响应错误12002。
我可以重现它的方法如下:
1.使用按钮从主窗口(A)打开窗口(B)
2.当单击按钮以打开窗口B时,窗口A同步调用ajax(PROC1)。PROC1运行文件。
3.新窗口(B)有ajax代码(PROC2),并异步调用服务器。运行良好。
4.在PROC2完成但返回数据之前,用户关闭窗口B。
5.在主窗口(a)中再次单击按钮。PROC1再次运行,但现在send()调用阻塞了5分钟。
请帮忙解决。我已经找了3天。
请注意: * 我无法在Firefox中测试它(该应用程序不兼容Firefox) * 我必须使用同步调用(这是应用程序构造的方式,重新编写它需要太多的开发人员工作量)
为什么会发生这种情况,如何修复?

只是一个建议,但使用“进程资源管理器”和“进程监视器”可以了解系统的内部运行情况。 - Terry
6个回答

7

你说得对,Jaap。这与Internet Explorer的连接限制有关,其限制为2。由于某种原因,IE不会释放在关闭窗口时执行的AJAX请求的连接。

我遇到了非常相似但稍微简单一些的情况:

  • 用户在窗口A中点击以打开窗口B
  • 窗口B执行一个需要一段时间的Ajax调用
  • 在Ajax调用返回之前,用户关闭了窗口B。此调用的连接“泄漏”了。
  • 重复1次,直到两个可用连接都被“泄漏”
  • 浏览器变得无响应

你可以尝试一种技术(在你找到的文章中提到),它似乎是有效的,那就是在页面的unload事件中中止XmlHttp请求。

所以大概是这样:

var xhr = null;

function unloadPage() {
  if( xhr !== null ) {
    xhr.abort();
  }
}

另一种选择是使用同步的AJAX调用,这将阻塞直到调用返回,从而锁定浏览器。在特定情况下,这可能是可以接受的,也可能不可接受。

// the 3rd param is whether the call is asynchronous
xhr.open( 'get', 'url', false );

最后,正如在其他地方提到的那样,您可以在注册表中调整IE使用的最大连接数。然而,期望访问您网站的访客这样做并不现实,而且它实际上并不能解决问题 - 只是将问题的发生延迟。顺便提一下,IE8将允许6个并发连接。


我曾使用一个中止方案来解决IE8中ajax和打开关闭窗口的非常相似的问题。然而,为了中止并不丢失我所需要的响应,我不得不在jQuery中使用async:false。这在我的情况下是可以接受的,但显然不是理想的。然而,中止确实解决了空白新窗口的问题。请参见https://dev59.com/VXRB5IYBdhLWcg3w-8Ho中的我的评论以获取更多细节。 - Carvell Fenton

2

事实上,当尝试从PHP脚本接收数据时,IE5和IE6确实会挂起。原因是这些浏览器无法确定什么时候已经接收到了所有的数据并且可以关闭连接。因此它们会一直等待直到连接超时(因此出现了5或10分钟的挂起情况)。解决这个问题的方法是告诉浏览器它将接收多少数据。在PHP中,您可以使用输出缓冲来做到这一点,例如:

ob_start();
echo $html_content;
header( 'Connection: close' );
header( 'Content-Length: '.ob_get_length() );
flush();
ob_end_flush();

当我们加载普通网页时,这是一个解决方案。当我们使用Microsoft.XMLHTTP对象通过AJAX GET请求时,只需在GET请求中发送“Connection:close”头即可。

r.request.open( "GET", url, true );
r.request.setRequestHeader( "Connection", "close" );
r.request.send();

2

感谢您回答Martijn。

它没有解决我的问题。我认为我看到的最好的描述在这个网站上: http://bytes.com/groups/javascript/643080-ajax-crashes-ie-close-window

在我的情况下,我有一个不稳定的连接或者一个慢速的web服务器,当连接太慢而浏览器和web服务器仍然保持连接时,就会冻结。


2
默认情况下,Internet Explorer仅允许两个并发连接到同一网站进行下载。如果您尝试启动更多的连接,IE会停滞,直到先前的请求完成,然后下一个请求才会完成。我认为(虽然可能错了),这是为了防止同时进行多个下载而导致网站过载。有一个注册表hack可以绕过此锁定。
我在互联网上找到了这些说明,缓解了我的问题-我不能保证它适用于您的情况,但您面临的多连接限制似乎相关:
1. 单击“开始”按钮,选择“运行”。 2. 在运行行上键入Regedt32.exe并按Enter。这将启动注册表编辑器。 3. 在注册表中找到以下密钥:HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings 4. 单击Internet设置密钥。 5. 现在转到编辑菜单,指向NEW 6. 单击DWORD值 7. 输入MaxConnectionsPer1_0Server作为此DWORD值的名称。 8. 双击刚创建的MaxConnectionsPer1_0Server键,并输入以下信息:值数据:10。基数:十进制。 9. 完成后按OK。 10. 重复步骤4到9。这次将密钥命名为MaxConnectionsPerServer,并分配与步骤8中指示的相同值。 11. 完成后按OK 12. 关闭注册表编辑器。
当然,我会将这些与先前提到的abort()调用一起使用。同时使用它们应该可以解决问题。

1

Winsock错误12002的含义如下,根据msdn所述:

ERROR_INTERNET_TIMEOUT

12002

The request has timed out.

Winsock是IE中XMLHTTP的底层套接字传输对象,因此任何不在HTTP错误范围(300、400、500等)内的错误几乎总是Winsock错误。

从您的问题中不清楚的是第二次查询是否使用相同的资源。您可以通过添加以下内容来强制使用新的未缓存资源:

'?uid=+'Math.random()

前往可能解决问题的URL。

另一个解决方案可能是将函数附加到窗口对象上的“onbeforeunload”事件,以在关闭窗口B之前调用abort()和任何活动的XMLHTTP请求。

希望这两个指针能解决您的错误。


0
所有这些帖子 - 禁用PDF阅读器等等...都不能解决您的问题... 但是肯定的方法是 - 运行Windows更新..保持最新..这个问题会自行解决.. 经验之谈 ;) HydTechie

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接