解析浏览器端的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内存泄露的一个好例子
Dec 09 Javascript
js实现遮罩层弹出框的方法
Jan 15 Javascript
AngularJS全局scope与Isolate scope通信用法示例
Nov 22 Javascript
使用vue.js实现联动效果的示例代码
Jan 10 Javascript
JavaScript中三种常见的排序方法
Feb 24 Javascript
微信小程序获取地理位置及经纬度授权代码实例
Sep 18 Javascript
node解析修改nginx配置文件操作实例分析
Nov 06 Javascript
VUE项目axios请求头更改Content-Type操作
Jul 24 Javascript
基于element-ui对话框el-dialog初始化的校验问题解决
Sep 11 Javascript
vue3.0 自适应不同分辨率电脑的操作
Feb 06 Vue.js
node.js 基于 STMP 协议和 EWS 协议发送邮件
Feb 14 Javascript
JavaScript 绘制饼图的示例
Feb 19 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
中国广播史趣谈 — 几个历史第一次
2021/03/01 无线电
使用php来实现网络服务
2009/09/15 PHP
详解PHP对数组的定义以及数组的创建方法
2015/11/27 PHP
php封装的连接Mysql类及用法分析
2015/12/10 PHP
php网页版聊天软件实现代码
2016/08/12 PHP
php使用pthreads v3多线程实现抓取新浪新闻信息操作示例
2020/02/21 PHP
限制文本框输入N个字符的js代码
2010/05/13 Javascript
JavaScript取得鼠标绝对位置程序代码介绍
2012/09/16 Javascript
jQuery(js)获取文字宽度(显示长度)示例代码
2013/12/31 Javascript
ie下$.getJSON出现问题的解决方法
2014/02/12 Javascript
node.js使用require()函数加载模块
2014/11/26 Javascript
node.js中的fs.writeFile方法使用说明
2014/12/14 Javascript
node.js中的fs.readlink方法使用说明
2014/12/17 Javascript
原生js实现模拟滚动条
2015/06/15 Javascript
jQuery实现的简单折叠菜单(折叠面板)效果代码
2015/09/16 Javascript
JavaScript常用字符串与数组扩展函数小结
2016/04/24 Javascript
详解vue2.0+vue-video-player实现hls播放全过程
2018/03/02 Javascript
webpack源码之loader机制详解
2018/04/06 Javascript
vue+webpack实现异步加载三种用法示例详解
2018/04/24 Javascript
vue采用EventBus实现跨组件通信及注意事项小结
2018/06/14 Javascript
详解js静态检查工具eslint配置文件
2018/11/23 Javascript
基于vue实现滚动条滚动到指定位置对应位置数字进行tween特效
2019/04/18 Javascript
详解vue 路由跳转四种方式 (带参数)
2019/04/28 Javascript
js实现蒙版效果
2020/01/11 Javascript
[03:01]DOTA2英雄基础教程 露娜
2014/01/07 DOTA
[36:05]DOTA2亚洲邀请赛 3.31 小组赛 A组 Liquid vs Optic
2018/04/01 DOTA
教你用Python写安卓游戏外挂
2018/01/11 Python
http请求 request失败自动重新尝试代码示例
2018/01/25 Python
Under Armour美国官网:美国知名高端功能性运动品牌
2016/09/05 全球购物
新西兰最大的连锁超市:Countdown
2020/06/04 全球购物
应聘医药代表职位求职信
2013/10/21 职场文书
妇女工作先进事迹
2014/08/17 职场文书
世界读书日的活动方案
2014/08/20 职场文书
群众路线自我剖析及整改措施
2014/11/04 职场文书
nginx配置ssl实现https的方法示例
2021/03/31 Servers
Oracle设置DB、监听和EM开机启动的方法
2021/04/25 Oracle