AJAX的阻塞及跨域名解析

 更新时间:2007年07月05日 00:00:00   作者:  
阻塞的AJAX请求

  我们先来证实一下请求的阻塞情况吧。我们使用如下的代码:

连续发起三个请求

function simpleRequest()
{
   var request = new XMLHttpRequest();
   request.open("POST", "Script.ashx");
   request.send(null);
}

function threeRequests()
{
   simpleRequest();
   simpleRequest();
   simpleRequest();
}

当执行threeRequests时就会连续发出3个相同域名的请求,还是通过统计图表来查看阻塞的效果,如图:
点击在新窗口中浏览此图片
每个请求需要花费1.5秒的时间。很明显,第三个请求必须等到第一个请求结束之后才能执行,因此总共需要进行3秒多钟才能执行完毕。我们要改变的就是这个状况。

传统的跨域名异步请求解决方案

  AJAX安全性的唯一保证,似乎就是对于跨域名(Cross-Domain)AJAX请求的限制。除非打开本地硬盘的网页,或者在IE中将跨域名传输数据的限制打开,否则向其他域名发出AJAX请求都会被禁止。而且对于跨域名的判断非常严格,不同的子域名,或者相同域名的不同端口,都会被认作是不同的域名,我们不能向它们的资源发出AJAX请求。

  从表面上看起来似乎没有办法打破这个限制,还好我们有个救星,那就是iframe!

  iframe虽然不在标准中出现,但是由于它实在有用,FireFox也“不得不”对它进行了支持(类似的还有innerHTML)。网上已经有一些跨域名发出异步请求的做法,但是它们实在做的不好。它们的简单工作原理如下:在另一个域名下放置一个特定的页面文件作为Proxy,主页面将异步请求的信息通过Query String传递入iframe里的Proxy页面,Proxy页面在AJAX请求执行完毕后将结果放在自己location的hash中,而主页面会对iframe的src的hash值进行轮询,一旦发现它出现了改变,则通过hash值得到需要的信息。

  这个方法的实现比较复杂,而且功能有限。在IE和FireFox中,对于URL的长度大约可以支持2000个左右的字符。对于普通的需求它可能已经足够了,可惜如果真要传递大量的数据,这就远远不够了。与我们一会儿要提出的解决方案相比,可能它唯一的优势就是能够跨任意域名进行异步请求,而我们的解决方案只能突破子域名的限制。

  那么现在来看看我们的做法!



优雅地突破子域名的限制

  我们突破子域名限制的关键还是在于iframe。

  iframe是的好东西,我们能够跨过子域名来访问iframe里的页面对象,例如window和DOM结构,包括调用JavaScript(通过window对象)——我们将内外页面的document.domain设为相同就可以了。然后在不同子域名的页面发起不同的请求,把结果通过JavaScript进行传递即可。唯一需要的也仅仅是一个简单的静态页面作为Proxy而已。

  我们现在就来开始编写一个原形,虽然简单,但是可以说明问题。

  首先,我们先来编写一个静态页面,作为放在iframe里的Proxy,如下:

SubDomainProxy.html

<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
   <title>Untitled Page</title>
   <script type="text/javascript" language="javascript">
       document.domain = "test.com";

       function sendRequest(method, url)
       {
           var request = new XMLHttpRequest();
           request.open(method, url);
           request.send(null);
       }
   </script>
</head>
<body>

</body>
</html>




  然后我们再编写我们的主页面:

http://www.test.com/Default.html

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
   <title>Untitled Page</title>
   <script type="text/javascript" language="javascript">
       document.domain = "test.com";

       function simpleRequest()
       {
           var request = new XMLHttpRequest();
           request.open("POST", "Script.ashx");
           request.send(null);
       }

       function crossSubDomainRequest()
       {
           var proxy = document.getElementById("iframeProxy").contentWindow;
           proxy.sendRequest('POST', 'http://sub0.test.com/Script.ashx');
       }

       function threeRequests()
       {
           simpleRequest();
           simpleRequest();
           crossSubDomainRequest();
       }
   </script>
</head>
<body>
   <input type="button" value="Request" onclick="threeRequests()" />
   <iframe src="http://sub0.test.com/SubDomainProxy.html" style="display:none;"
       id="iframeProxy"></iframe>
</body>
</html>




  当执行threeRequests方法时,将会同时请求http://www.test.com以及http://sub0.test.com两个不同域名下的资源。很明显,最后一个请求已经不会受到前两个请求的阻塞了 如图:


点击在新窗口中浏览此图片
令人满意的结果!

  虽说只能突破子域名,但是这已经足够了,不是吗?我们为什么要强求任意域名之间能够异步通讯呢?更何况我们的解决方案是多么的优雅!在下一篇文章中,我们将会为ASP.NET AJAX客户端实现一个完整的CrossSubDomainRequestExecutor,它会自动判断是否正在发出跨子域名的请求,并选择AJAX请求的方式。这样,客户端的异步通讯层就会对开发人员完全透明。世上还会有比这更令人愉快的事情吗?:)



注意事项

  可能以下几点值得一提:

我在出现这个想法之后也作了一些尝试,最后发现创建XMLHttpRequest对象,调用open方法和send方法都必须在iframe中的页面中执行才能够在IE和FireFox中成功发送AJAX请求。
在上面的例子中,我们向子域名请求的的路径是http://sub0.test.com/Script.ashx。请注意,完整的子域名不可以省略,否则在FireFox下就会出现权限不够的错误,在调用open方法时就会抛出异常——似乎FireFox把它当作了父页面域名的资源了。
Windows Live Contacts Gadget使用了一种叫做Channel的技术,用于解决跨任意域名传递数据的问题,我相当佩服微软技术人员的创造力。Channel技术是一种优秀的解决跨域名异步请求问题的解决方案,而且如果将它封装成了组件,那么使用起来也会相当优雅(似乎微软已经准备这么做了)。不过它和我们现在需要解决的问题并不相同,如果有机会的话,我也会详细的解释一下Channel技术——但不是现在,因为我觉得我还没有完全理解这个技术本身。

原文:
作者:赵劼 http://www.cnblogs.com/JeffreyZhao/archive/2007/02/02/Break_the_Browsers_Restrictions_6.html

相关文章

  • iframe式ajax调用示例代码

    iframe式ajax调用示例代码

    这篇文章主要介绍了iframe式ajax调用,需要的朋友可以参考下
    2014-05-05
  • Ajax乱码问题整理

    Ajax乱码问题整理

    Ajax乱码问题整理...
    2006-09-09
  • Ajax实现文件下载

    Ajax实现文件下载

    本文给大家介绍ajax实现文件下载相关知识,涉及到ajax文件下载方面的知识,本文介绍的非常详细,具有参考借鉴价值,感兴趣的朋友一起学习吧
    2016-03-03
  • Ajax与用户交互的JSON数据存储格式

    Ajax与用户交互的JSON数据存储格式

    数据存储是JavaScript的核心功能,适当的存放好数据,就有利于我们组织起结构,又能使应用程序稍后访问这些内容更加容易。这篇文章给大家介绍了Ajax与用户交互的JSON数据存储格式,感兴趣的朋友一起看看吧
    2016-11-11
  • Ajax bootstrap美化网页并实现页面的加载删除与查看详情

    Ajax bootstrap美化网页并实现页面的加载删除与查看详情

    Bootstrap是Twitter推出的一个开源的用于前端开发的工具包,Bootstrap提供了优雅的HTML和CSS规范,它即是由动态CSS语言Less写成。下面通过本文给大家介绍Ajax bootstrap美化网页并实现页面的加载删除与查看详情,需要的朋友可以参考下
    2017-03-03
  • 如何利用jQuery post传递含特殊字符的数据

    如何利用jQuery post传递含特殊字符的数据

    在jquery中,解决数据传递处理的方法我们通常利用$.ajax或$.post,但是这里这里通常不能传递特殊字符,比如说:“<”,本文就帮大家解决如何传递这种含特殊字符的数据,感兴趣的朋友一起看下吧
    2015-10-10
  • Ajax返回值类型与用法实例分析

    Ajax返回值类型与用法实例分析

    这篇文章主要介绍了Ajax返回值类型与用法,结合实例形式分析了ajax返回值的xml类型与文本类型详细分类、用法与相关操作注意事项,需要的朋友可以参考下
    2019-07-07
  • ajax以及一些乱码问题

    ajax以及一些乱码问题

    很就以前在使用AJAX的时候,那时候还不知道AJAX。于是在任务中被AJAX的乱码问题搞的头破血流。
    2010-08-08
  • Ajax request response 乱码解决方法

    Ajax request response 乱码解决方法

    今天最早遇到一个脱离平台,单独给用户定制开发的关于状态管理的功能局部刷新出现乱码的情况,仔细查了下代码发现并无特殊之处,charset统一使用GB18030,ajax传递参数使用默认UTF-8,对传递的中文信息手动转码。
    2009-05-05
  • 防止重复发送Ajax请求的解决方案

    防止重复发送Ajax请求的解决方案

    这篇文章主要介绍了防止重复发送Ajax请求的解决方案,感兴趣的小伙伴们可以参考一下
    2016-01-01

最新评论