ajax源码解析-$.ajax()中常见应用示例

$.ajax()中常见应用示例

cacheifModified参数 跨域请求

cache和ifModified参数

1) cache参数:GET和POST最重要的区别
语义上,GET是获取指定URL上的资源,是读操作,重要的一点是不论对某个资源GET多少次,它的状态是不会改变的,在这个意义上,我们说GET是安全的(不是被密码学或者数据保护意义上的安全)。因为GET是安全的,所以GET返回的内容可以被浏览器,Cache服务器缓存起来。
而POST的语意是对指定资源“追加/添加”数据,所以是不安全的,每次提交的POST,参与的代码都会认为这个操作会修改操作对象资源的状态,于是,浏览器在你按下F5的时候会跳出确认框,缓存服务器不会缓存POST请求返回内容。
2) ifModified参数:
通过ifModified参数提高请求性能(即:“条件GET”:Last-Modified / If-Modified-Since和ETag / If-None-Match)
当你请求的资源并不是一层不变的时候,即不能简单的一直使用客户端缓存时,你可能通过将cache设置为false来发送请求,这实际上是在url加上时间戳组合成新的url,每次发送新的请求,这明显加大了服务器的压力。
对于这种情况,我们可以通过ifModified参数改进缓存方式(即:cache和ifModified都设置为true),仅在请求的数据改变时重新获取。通过这种方式请求的url不会改变,并且每次都会发送到服务器,只是会有检验方法验证是否需要重新获取数据从而节省带宽和开销。
更多ETag描述(优点,解决了Last-Modified无法解决的一些问题,什么场合不应该被使用)

过程如下:
a) 将$.ajax()函数的cache和ifModified参数同时设置为true。
b) 客户端请求服务端A,在服务端加上Last-Modified/ETag响应体一起返回
c) 客户端缓存接收到的Last-Modified/ETag响应体,并在下一次发生请求A时将缓存的Last-Modified/ETag值做为If-Modified-Since/IF-None-Match请求头一起发给服务器
d) 服务器接收If-Modified-Since/IF-None-Match后, 就根据参数值检验自上次客服端请求之后资源是否有改动
i. 若还未改动则直接返回响应304和一个空的响应体。
ii. 若已改动则重新处理数据,返回最新的请求数据。
e) 这样,既保证不向客户端重复发出资源,也保证当服务器有变化时,客户端能够得到最新的资源。
这一过程中,我们只需要做:服务器返回Last-Modified/ETag响应头和在服务端检验数据是否失效并采取对应处理方式。其余步骤由jQuery框架的ajax()函数完成。

关键代码如下:
客服端:

$('#btn_nowTime_long3').bind('click', null
, function () {
$.ajax('AjaxHandler.ashx?func=GetServerTime4Modified',
{
type: 'get',
dataType: 'text',
cache: true,
ifModified: true,
success: function (data) {
if (data)
alert(data);
},
});
});

服务端:

if(!String.IsNullOrEmpty(context.Request.Headers["If-Modified-Since"]))
{
if (CheckResourceValidate()) // 检查资源有效性
{
// 如果资源有效,则直接返回304状态码,客户端回去到此状态码后会从缓存中取值。
context.Response.StatusCode = 304;
return;
}
}
// 请求数据
GetServerTimeAfter2Second();
context.Response.Cache.SetExpires(DateTime.Now.AddSeconds(5));
// 设置Last-Modified响应体
context.Response.Cache.SetLastModified(DateTime.Now);

跨域请求

在JavaScript中,有一个很重要的安全性限制,被称为“Same-Origin Policy”(同源策略)。这一策略对于JavaScript代码能够访问的页面内容做了很重要的限制,即JavaScript只能访问与包含它的文档在同一域下的内容。所谓同源是指,域名(host),协议(protocol),端口(port)相同。

URL 说明 是否允许通信 能否通过javascript解决
http://www.a.com/a.js http://www.a.com/b.js 同一域名下 允许
http://www.a.com/lab/a.js http://www.a.com/script/b.js 同一域名下不同文件夹 允许
http://www.a.com:8000/a.js http://www.a.com/b.js 同一域名,不同端口 不允许
http://www.a.com/a.js https://www.a.com/b.js 同一域名,不同协议(http和https) 不允许 不能
http://www.a.com/a.js http://70.32.92.74/b.js 域名和域名对应ip 不允许
http://www.cnblogs.com/a.js http://www.a.com/b.js http://script.a.com/b.js http://a.com/b.js 不同域名(host) 不允许

1) $.ajax()为我们提供了两种解决方案 ,不过都是只支持get方式,分别是jQuery的jQuery.ajax“jsonp”格式和jquery.getScript()(即jQuery.ajax “script”格式)方式。
2) $.ajax()跨域原理分析
由于javascript的安全限制“同源策略”,所以我们无法使用XMLHttpRequest直接请求别的域名下的资源。不过拥有src属性和href属性的script\img\iframe和link\a标签不受同源策略影响。
$.ajax()提供的两种解决方案正是应用了动态创建script的方式来实现(即:生成script标签,src引入脚本,然后执行,最后移除script标签)。

3) jQuery.ajax()的jsonp和script方式的异同点:
a) 相同:都走$.ajax() script格式的流程;不会触发全局事件和局部事件;只支持GET方式(POST请求会自动转化为GET请求);默认不启用缓存(cache:false)
b) 不同:jsonp方式可以通过jsonp和jsonpCallback参数指定一个特定回调函数。
4) 示例部署说明:
因为是跨域请求,所以需要在本机部署两个示例程序以模拟不同域之间的访问,并且在示例代码中需要修改“crossUrl”为目的域路径。
5) jsonp示例代码:

客服端:

// jsonp方式跨域请求(dataType:jsonp)
$('#btn_cross_req1').bind('click', null
, function () {
$.ajax(crossUrl,
{
type: 'get',
dataType: 'jsonp',
jsonp: 'jsonpParamName',
jsonpCallback: 'crossCallback',
crossDomain: true,
});
});
function crossCallback(data) {
alert('jsonp' + data);
}

服务端:

context.Response.ContentType = "text/plain";
string jsonpCallbackName = reqCollection["jsonpParamName"];
context.Response.Write(String.Format("{0}('来自域:{1}的相应信息')", jsonpCallbackName, context.Request.Url.Host));

分析:
a) 因jsonp和jsonpCallback参数而改变的url如下。(即默认为:callback=jQuery随机值,更改为:jsonpParamName=crossCallback)
URL:http://192.168.1.100:6567/AjaxHandler.ashx?func=CrossRequest&jsonpParamName=crossCallback&_=1368360234428
b) 服务器端获取到jsonp回调函数名后,返回一个函数表达式。
6) 在XMLHttpRequest Level 2中新增了跨域访问方式、接收二进制等新功能,详细请看:XMLHttpRequest2 新技巧

sunbaixin wechat
欢迎您扫一扫上面的微信公众号,订阅我的博客!