解析浏览器端的AJAX缓存机制


Posted in Javascript onJune 21, 2016

AJAX的缓存是由浏览器维持的,对于发向服务器的某个url,ajax仅在第一次请求时与服务器交互信息,之后的请求中,ajax不再向服务器提交请求,而是直接从缓存中提取数据。
有些情况下,我们需要每一次都从服务器得到更新后数据。思路是让每次请求的url都不同,而又不影响正常应用:在url之后加入随机内容。
e.g.

url=url+"&"+Math.random();

Key points:
1.每次请求的url都不一样(ajax的缓存便不起作用)
2.不影响正常应用(最基本的)

这里我们由两条结论:

1:Ajax的缓存和HTTP的缓存是一样的
现代浏览器的HTTP和缓存机制比Ajax的XMLHttpRequest对象要差很多,所以它不认识也不关心Ajax请求.它仅仅是遵循普通的HTTP缓存规则,通过服务器返回的响应头来进行缓存.
如果你已经对 HTTP缓存 有了解,那么你可以把HTTP缓存的知识用对Ajax缓存的理解上. 他们只有一点不同的,就是设置响应头的方式会和普通文件不一样.
下面这些响应头可以让你的Ajax可缓存:
Expires: 这一项应该被设置成未来的某个合适的时间点,时间点的设置取决于内容变动的频繁程度.举个栗子,如果请求的是个库存数量,那么Expires的值可以是10秒以后.如果请求的是一个相片,那么Expires的值就可以久一点,因为它不会经常变动.Expires头可以让浏览器在一段时间内重用本地缓存数据,从而避免任何不必要的与服务器数据交互.
Last-Modified: 设置这一项是一个很好的选择,通过它,浏览器在发送条件性GET请求的时候会使用请求头里的 If-Modified-Since 来检查本地缓存的内容.如果数据不需要更新,服务器会返回304响应状态.
Cache-Control: 在合适的情况下,这个值应该被设置为 Public ,这样所有的中间代理和缓存都可以被保存并且与其他用户共享内容.在火狐里,它还支持HTTPS请求的缓存
当然,如果你使用POST方式发送Ajax是不能缓存的,因为POST请求永远不会被缓存.如果你的Ajax请求会产生其他作用(比如银行账户之间的转账),请使用POST请求.
我们设置了一个demo(这个demo已经不能看了?(?□?)ノ)来阐明这些头信息是如何工作的. 在HttpWatch里,你可以看到我们在响应头信息里设置了以上三个响应头

解析浏览器端的AJAX缓存机制

如果你规律的点击 ‘Ajax Update' 按钮,时间的改变会趋向于每隔一分钟一次.因为Expires响应头被设置为未来的一分钟.在下面这张截图里你可以看到:重复的点击更新按钮时,Ajax请求会读取浏览器本地的缓存而不会产生网络活动(发送和传输栏的值都是0)

解析浏览器端的AJAX缓存机制

最后一次1:06.531时刻的点击发送的Ajax请求产生了网络数据传输,因为缓存的数据已经超过了一分钟. 服务器返回200响应状态表示获取到了一份新的数据.
猜测这个demo应该是一个按钮,每点击一次获取一次当前时间然后回现在页面上.

2:IE浏览器在Expires时间过期之前不会刷新通过Ajax获取的内容.
有些时候,Ajax在页面加载的时候就被用来填充页面的某些部分(比如一个价格列表).它并不是通过用户的某个事件(比如点击某个按钮)触发的,而是在页面加载的时候就通过javascript来发送的.就好像Ajax请求和那些嵌入资源(比如js和css)是一样的.
如果你开发这样的页面,在刷新它的时候,很可能想要更新嵌入的Ajax请求内容.对于嵌入资源(CSS文件,图片等),浏览器会通过用户刷新的方式是F5(刷新)还是Ctrl+F5(强制刷新)来自动发送下列不同类型的请求:
1.F5(刷新): 如果请求内容带有 Last-Modified 响应头,那么浏览器会发送条件性更新请求. 它使用 If-Modified-Since 请求头进行比较,这样服务器就可以返回304状态来避免传输不必要的数据.
2.Ctrl+F5(强制刷新): 告诉浏览器发送无条件更新请求,请求头的 Cache-Control 被设置为‘no-cache'.这告诉所有的中间代理和缓存:浏览器需要获取最新的版本,无论它是否已经被缓存.
Firefox把这个刷新的方式传播到了那些在页面加载的时候就发送的Ajax请求上,把这些Ajax请求当成嵌入资源来处理.下面是HttpWatch在火狐下的截图,显示了Ajax Caching demo(这个demo已经不能看了?(?□?)ノ)刷新(F5)页面时Ajax请求的效果:

解析浏览器端的AJAX缓存机制

火狐确保Ajax发起的请求是条件性的.在这个例子里,如果缓存数据不到10秒,服务器返回304,超过10秒,服务器返回200,重新传送数据.
在ie里,加载页面时就发起的Ajax请求被看做是和页面其他部分刷新毫无关系的,也不会被用户的刷新方式所左右.如果缓存的ajax数据没有过期,就不会有GET请求发送到服务器.它会直接从缓存里读取数据,从HttpWatch里看就是(Cache)结果.下面这个图是在ie下缓存没有过期的情况下按F5刷新:

解析浏览器端的AJAX缓存机制

就算是通过 Ctrl+F5 强制刷新,通过Ajax获取的数据也是从缓存里读取:

解析浏览器端的AJAX缓存机制

这就意味着,任何通过Ajax得到的内容如果没有过期,在ie下都不会被更新 - 即使你使用Ctrl+F5强制刷新. 唯一能确保你获取最新数据的方法就是手动清楚缓存. 可以使用HttpWatch的工具栏:

解析浏览器端的AJAX缓存机制

注意,Cache结果和304结果是不同的.Cache其实是200(cache),304就是304.Cache其实没有向服务器发送请求,可以从chrome里看到,它的耗时是0,response也是空.而304不同,
304请求是浏览器发起了一个条件性的请求,这个请求携带了 If-Modified-Since 请求头,如果这个文件在浏览器发送的这个时间之后没有修改过,服务器端就回返回一个304状态,告诉浏览器使用它本地的缓存内容.它没有Cache快,因为请求还是发送到了服务器端,只不过服务器端没有发送数据.
可以看下taobao首页,里面既有200(cache)也有304.可以查看他们的区别.

总结:

我们都知道,ajax能提高页面载入的速度的主要原因是通过ajax减少了重复数据的载入,真正做到按需获取,既然如此,我们在写ajax程序的时候不妨送佛送到西,在客户端再做一次缓存,进一步提高数据载入速度。那就是在载入数据的同时将数据缓存在浏览器内存中,一旦数据被载入,只要页面未刷新,该数据就永远的缓存在内存中,当用户再次查看该数据时,则不需要从服务器上去获取数据,极大的降低了服务器的负载和提高了用户的体验。

Javascript 相关文章推荐
xml文档转换工具,附图表例子(hta)
Nov 17 Javascript
JQuery实现用户名无刷新验证的小例子
Mar 22 Javascript
JavaScript全排列的六种算法 具体实现
Jun 29 Javascript
js实现倒计时(距离结束还有)示例代码
Jul 24 Javascript
Jquery 获取对象的几种方式介绍
Jan 17 Javascript
jQuery中;function($,undefined) 前面的分号的用处
Dec 17 Javascript
jquery限定文本框只能输入数字(整数和小数)
Jan 08 Javascript
基于JavaScript实现类似于百度学术高级检索功能
Mar 02 Javascript
JS实现下拉菜单列表与登录注册弹窗效果
Aug 10 Javascript
js指定日期增加指定月份的实现方法
Dec 19 Javascript
js实现select下拉框选择
Jan 11 Javascript
Vue-cli4 配置 element-ui 按需引入操作
Sep 11 Javascript
JS实现对中文字符串进行utf-8的Base64编码的方法(使其与Java编码相同)
Jun 21 #Javascript
第十篇BootStrap轮播插件使用详解
Jun 21 #Javascript
JavaScript简单获取页面图片原始尺寸的方法
Jun 21 #Javascript
第九篇Bootstrap导航菜单创建步骤详解
Jun 21 #Javascript
js简单判断flash是否加载完成的方法
Jun 21 #Javascript
第八篇Bootstrap下拉菜单实例代码
Jun 21 #Javascript
JS实现获取剪贴板内容的方法
Jun 21 #Javascript
You might like
在WINDOWS中设置计划任务执行PHP文件的方法
2011/12/19 PHP
PHP管理内存函数 memory_get_usage()使用介绍
2012/09/23 PHP
在laravel中使用with实现动态添加where条件
2019/10/10 PHP
jQuery结合Json提交数据到Webservice,并接收从Webservice返回的Json数据
2011/02/18 Javascript
浅析Prototype的模板类 Template
2011/12/07 Javascript
jquery.post用法关于type设置问题补充
2014/01/03 Javascript
ZeroClipboard插件实现多浏览器复制功能(支持firefox、chrome、ie6)
2014/08/30 Javascript
node.js中的console.time方法使用说明
2014/12/09 Javascript
jQuery选择器源码解读(一):Sizzle方法
2015/03/31 Javascript
分享10个原生JavaScript技巧
2015/04/20 Javascript
JS实现横向与竖向两个选项卡Tab联动的方法
2015/09/27 Javascript
js原型链与继承解析(初体验)
2016/05/09 Javascript
VUEJS实战之修复错误并且美化时间(2)
2016/06/13 Javascript
Javascript实现时间倒计时功能
2018/11/17 Javascript
Element UI框架中巧用树选择器的实现
2018/12/12 Javascript
NodeJs实现简易WEB上传下载服务器
2019/08/10 NodeJs
layuiAdmin循环遍历展示商品图片列表的方法
2019/09/16 Javascript
Vue实现base64编码图片间的切换功能
2019/12/04 Javascript
vscode调试node.js的实现方法
2020/03/22 Javascript
jQuery实现鼠标拖拽登录框移动效果
2020/09/13 jQuery
Python实现简单的语音识别系统
2017/12/13 Python
详解Python3网络爬虫(二):利用urllib.urlopen向有道翻译发送数据获得翻译结果
2019/05/07 Python
python字符串的index和find的区别详解
2020/06/20 Python
Python APScheduler执行使用方法详解
2020/12/10 Python
HTML5 Canvas像素处理使用接口介绍
2012/12/02 HTML / CSS
意大利简约的休闲品牌:Aspesi
2018/02/08 全球购物
香港连卡佛百货官网:Lane Crawford
2019/09/04 全球购物
小学班干部竞选演讲稿
2014/04/24 职场文书
法制宣传口号
2014/06/16 职场文书
家具商场的活动方案
2014/08/16 职场文书
村干部四风问题整改措施
2014/09/30 职场文书
2015年“七七卢沟桥事变”纪念活动总结
2015/03/24 职场文书
2015年学校消防安全工作总结
2015/10/14 职场文书
《游戏公平》教学反思
2016/02/20 职场文书
vue使用watch监听属性变化
2022/04/30 Vue.js
Python可视化神器pyecharts绘制地理图表
2022/07/07 Python