在上次的文章中,我们已经提到了一种能够跨子域名进行AJAX请求的方法。我们现在就来实现一个对开发人员透明的实现,它会自动判断这个请求是否是跨子域名,如果不是,则使用传统的方法发出AJAX请求,反之则使用我们的方式。
我在如何实现这个Executor的问题上,我想了很久。按照ASP.NET AJAX的“标准”来说,应该开发一个WebRequestExecutor的子类,然后将其设为默认的Executor或者某个特定WebRequest的Executor。但是最终我使用了直接修改XMLHttpExecutor的做法,因为考虑到以下原因:
完整实现一个WebRequestExecutor需要实现太多接口,而CrossSubDomainExecutor和XMLHttpExecutor有太多相同的地方。
如果继承WebRequestExecutor的话,还是需要了解XMLHttpExecutor的太多细节,JavaScript做不到太好的封装,无法实现真正的面向对象。
CrossSubDomainExecutor在普通情况下和XMLHttpExecutor的行为一模一样。
直接修改XMLHttpExecutor的做法其实就是在XMLHttpExecutor的prototype上做文章,这也就是JavaScript扩展对象的一贯做法。
首先,我们定义一个Sys.Net.WebRequest类的静态方法,用来从一个URL中获得域名。例如输入http://www.sample.com/Default.aspx这个URL,返回http://www.sample.com,这个静态函数对于判断是否Cross Domain非常重要,如下:
Sys.Net.WebRequest._getRawDomain静态方法
Sys.Net.WebRequest._getRawDomain = function(url)
{
url = Sys.Net.WebRequest._resolveUrl(url);
var index = url.indexOf('://');
var prefix = url.substring(0, index + 3);
var url = url.substring(index + 3);
index = url.indexOf('/');
if (index < 0)
{
index = url.indexOf('?');
}
if (index >= 0)
{
url = url.substring(0, index);
}
return prefix + url;
}
其次,我们为Sys.Net.WebRequest类扩展一个,用于检测请求能否直接发出,而不需要使用我们的方法。在这里我们直接使用了一个XMLHttpRequest对象作为尝试:
Sys.Net.WebRequest._checkIfIsCrossDomainRequest方法
Sys.Net.WebRequest.prototype._checkIfIsCrossDomainRequest = function()
{
var request = new XMLHttpRequest();
try
{
request.open('get', this.get_url());
return false;
}
catch(e)
{
return true;
}
}