解析浏览器端的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 相关文章推荐
js获取变量
Aug 24 Javascript
js将iframe中控件的值传到主页面控件中的实现方法
Mar 11 Javascript
利用js实现禁止复制文本信息
Jun 03 Javascript
javascript常用的方法分享
Jul 01 Javascript
JavaScript对象数组的排序处理方法
Oct 21 Javascript
JS基于Ajax实现的网页Loading效果代码
Oct 27 Javascript
jQuery使用$.each遍历json数组的简单实现方法
Apr 18 Javascript
js停止冒泡和阻止浏览器默认行为的简单方法
May 15 Javascript
jQuery插件echarts实现的去掉X轴、Y轴和网格线效果示例【附demo源码下载】
Mar 04 Javascript
Vue+Vux项目实践完整代码
Nov 30 Javascript
微信小程序实现图片选择并预览功能
Jul 25 Javascript
layer.confirm点击第一个按钮关闭弹出框的方法
Sep 09 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
php打开文件fopen函数的使用说明
2013/07/05 PHP
Yii2创建多界面主题(Theme)的方法
2016/10/08 PHP
php正则去除网页中所有的html,js,css,注释的实现方法
2016/11/03 PHP
浅谈PHP的数据库接口和技术
2016/12/09 PHP
JavaScript中的History历史对象
2008/01/16 Javascript
js函数使用技巧之 setTimeout(function(){},0)
2009/02/09 Javascript
jquery 获取dom固定元素 添加样式的简单实例
2014/02/04 Javascript
javascript得到当前页的来路即前一页地址的方法
2014/02/18 Javascript
在JS数组特定索引处指定位置插入元素的技巧
2014/08/24 Javascript
js实现获取焦点后光标在字符串后
2014/09/17 Javascript
解决JS请求服务器gbk文件乱码的问题
2015/10/16 Javascript
Javascript实现页面滚动时导航智能定位
2017/05/06 Javascript
详解基于Vue-cli搭建的项目如何和后台交互
2018/06/29 Javascript
基于Nodejs的Tcp封包和解包的理解
2018/09/19 NodeJs
puppeteer库入门初探
2019/01/09 Javascript
ElementUI多个子组件表单的校验管理实现
2019/11/07 Javascript
微信小程序实现锚点功能
2019/11/20 Javascript
[00:17]天涯墨客一技能展示
2018/08/25 DOTA
在Python的Django框架中创建语言文件
2015/07/27 Python
Python  pip安装lxml出错的问题解决办法
2017/02/10 Python
python 调用c语言函数的方法
2017/09/29 Python
Python实现k-means算法
2018/02/23 Python
30秒轻松实现TensorFlow物体检测
2018/03/14 Python
Python Django 前后端分离 API的方法
2019/08/28 Python
Python3显示当前时间、计算时间差及时间加减法示例代码
2019/09/07 Python
Django关于admin的使用技巧和知识点
2020/02/10 Python
浅析python标准库中的glob
2020/03/13 Python
Python读取二进制文件代码方法解析
2020/06/22 Python
django下创建多个app并设置urls方法
2020/08/02 Python
使用OpenCV校准鱼眼镜头的方法
2020/11/26 Python
详解css3中的伪类before和after常见用法
2020/11/17 HTML / CSS
松本清官方海外旗舰店:日本最大的药妆连锁店
2017/11/21 全球购物
波兰在线儿童和婴儿用品零售商:pinkorblue
2019/06/29 全球购物
银行职员自我鉴定
2014/04/20 职场文书
后勤管理员岗位职责
2014/08/27 职场文书
大学生团支书竞选稿
2015/11/21 职场文书