转载
事情的经过是这样的,还是那个个人门户网站。其中有个功能就是RSS订阅,每个订阅作为一个模块出现在页面上。如果一个用户订阅了比较多的RSS,则在打开页面时所有的RSS模块就会开始加载,这时候可能就会需要十几秒甚至更长的时间才能加载完毕。这时,如果用户需要作别的AJAX操作——比如保存页面设置——那么长时间的等待就不可避免了,谁让浏览器对于相同域名只能同时存在两个连接呢?不过这可不是一个好的用户体验,那么我们需要怎么做呢?
第一种做法可能比较容易想到,我们可以自己编写代码维护一个Priority Queue,为每个请求附加一个“优先级”信息,这样我们就可以把重要的请求率先发出。这样就可以在一定程度上解决用户的等待问题。可惜这个方法还是无法突破两个连接的限制。于是第二种做法,我们就要设法突破两个连接的限制了。如果能够向别的域名发出AJAX请求,不也就能避免重要的请求被大量的请求所阻塞了吗?
我们还是从头看起,一点一点地来解决这个问题。
阻塞的AJAX请求
我们先来证实一下请求的阻塞情况吧。我们使用如下的代码:
连续发起三个请求
function simpleRequest()
{
var request = new XMLHttpRequest();
request.open("POST", "Script.ashx");
request.send(null);
}
function threeRequests()
{
simpleRequest();
simpleRequest();
simpleRequest();
}
当执行threeRequests时就会连续发出3个相同域名的请求,还是通过统计图表来查看阻塞的效果(如图11):
图11:最后的请求被前两个请求阻塞
每个请求需要花费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两个不同域名下的资源。很明显,最后一个请求已经不会受到前两个请求的阻塞了(如图12):
图12:不同域名的请求不会被阻塞
令人满意的结果!
虽说只能突破子域名,但是这已经足够了,不是吗?我们为什么要强求任意域名之间能够异步通讯呢?更何况我们的解决方案是多么的优雅!在下一篇文章中,我们将会为ASP.NET AJAX客户端实现一个完整的CrossSubDomainRequestExecutor,它会自动判断是否正在发出跨子域名的请求,并选择AJAX请求的方式。这样,客户端的异步通讯层就会对开发人员完全透明。世上还会有比这更令人愉快的事情吗?:)
分享到:
相关推荐
AJAX(Asynchronous JavaScript and XML)是一种非常流行的Web开发技术,但是它也存在一些问题,其中之一就是阻塞和跨域名访问问题。在本文中,我们将讨论AJAX的阻塞原因和跨域名解决方案。 AJAX阻塞的原因 当我们...
跨站点请求伪造(CSRF/XSRF)是一种攻击手段,攻击者通过诱使受害者访问恶意构造的网页链接,从而利用受害者的身份在受害者的权限范围内执行某些操作。通常情况下,这些操作是在受害者不知情的情况下发生的,这可能会...
**跨站Ajax(Flash Ajax)** 在Web开发中,AJAX(Asynchronous JavaScript and XML)是一种用于创建动态和交互性网页的技术。它允许在不重新加载整个页面的情况下,与服务器交换数据并更新部分网页内容。然而,AJAX...
- **同源策略**:出于安全考虑,Ajax请求受到同源策略限制,即只能请求同源(协议、域名、端口都相同)的资源。若需跨域,需使用CORS(跨源资源共享)或其他方式。 - **缓存处理**:Ajax请求默认会缓存结果,如果...
由于同源策略的限制,AJAX请求通常只能访问同源(协议、域名、端口相同)的资源。为实现跨域,可以使用JSONP或者CORS(跨源资源共享)技术。 ### 9. jQuery与AJAX库 为了简化AJAX操作,开发者通常会使用jQuery或...
6. **Domain属性(仅限子域)**:在cookies中设置`domain`属性可以实现跨子域共享,但这仅限于同一主域下的子域名之间,对AJAX跨域请求帮助有限。 在实际应用中,开发者通常根据项目需求和服务器环境选择合适的跨域...
由于同源策略限制,AJAX请求通常只能访问同一域名下的资源。为解决跨域问题,可以采用JSONP、CORS(跨源资源共享)或代理服务器等方法。 ### 6. AJAX的最佳实践 - **避免阻塞UI**:尽量使用异步请求,避免用户等待...
如果指定具体的域名,那么只有该域名下的页面可以访问。 2. Ext.Ajax.request的跨域配置: 要使用Ext.Ajax.request进行跨域,你需要在请求配置中添加`withCredentials`属性(表示是否携带cookies)以及`headers`...
5. **跨域问题**:由于同源策略,Ajax请求通常只能访问同源(协议+域名+端口)的资源。如果需要跨域,需要服务器端设置CORS(跨源资源共享)头或者使用JSONP(JSON with Padding)。 6. **错误处理**:通过onerror...
- 同源策略限制:默认情况下,Ajax只能访问同源(协议、域名、端口相同)的资源。 - SEO问题:搜索引擎爬虫可能无法抓取通过Ajax加载的内容。 - 前进/后退功能:不正确处理可能导致历史记录失效,影响用户导航。 ##...
5. 跨域请求:默认情况下,AJAX请求受到同源策略限制,只能访问同一域名下的资源。但通过JSONP(JSON with Padding)或CORS(跨源资源共享)技术,可以实现跨域请求,扩大数据来源范围。 6. AJAX进度控制:...
然而,有时我们需要从不同的域名获取数据,例如使用第三方API服务,这时就需要借助Ajax的跨域访问能力。jQuery库提供了一种简单的方式来处理这种需求,这就是本文将要讨论的主题。 ### 一、什么是跨域? 跨域是...
在Web开发中,由于同源策略的限制,JavaScript通常无法直接访问不同源的资源,但随着Web服务的广泛应用,跨域请求的需求日益增加。jQuery,作为一个强大的JavaScript库,提供了便捷的方式来处理这种问题,特别是通过...
由于同源策略限制,Ajax请求通常只能访问同源(协议+域名+端口相同)的资源。但通过CORS(跨源资源共享)或者JSONP(JSON with Padding)可以实现跨域请求。 ### 六、注意事项 1. **异步处理**:Ajax请求是异步的...
6. **跨域问题**:默认情况下,由于同源策略的限制,Ajax请求只能访问同源(协议、域名、端口相同)的资源。解决跨域问题的方法有JSONP、CORS(跨源资源共享)等。 7. **安全考虑**:使用Ajax时必须注意安全性,...
由于同源策略限制,Ajax请求通常只能访问同一域名下的资源。跨域请求需要服务器设置CORS(跨源资源共享)头,或者使用JSONP(JSON with Padding)技术。 通过学习黑马程序员的Ajax笔记,你可以深入了解Ajax的工作...
但是,通过CORS(跨域资源共享)机制,服务器可以明确指定哪些域名可以跨域访问其资源,从而实现了跨域请求的能力。 ### 7. AJAX与前端框架 现代前端开发中,许多流行的框架如React、Vue和Angular都内置了对AJAX的...
7. **跨域问题**:默认情况下,Ajax请求遵循同源策略,即只能访问同源(协议、域名、端口相同)的资源。为了实现跨域请求,可以使用CORS(跨源资源共享)或者JSONP(JSON with Padding)。 8. **Ajax库和框架**:...
7. **跨域问题**:由于同源策略的限制,Ajax请求通常只能访问同一域名下的资源。书中会讲解如何使用JSONP、CORS等技术解决跨域问题,以实现不同源间的通信。 8. **安全性考虑**:Ajax应用的安全问题不容忽视,如XSS...