这里不是关于像nodejs那样的服务端js,运行在页面中的js想直接获取http流中的Header是很困难的,出于安全的考虑也是不被允许的,
庆幸的是:还好各大浏览器都已经提供了对Last-Modified的支持,好像这是提供的唯一的Header,用js通过document.lastModified就能直接访问到。
悲剧的是:各大浏览器对读取这一Header的支持没有一个统一的规范,兼容性实在不敢恭维。
差异1,
在服务端有发送 Last-Modified Header 的情况下,也就是Http流中包含有该Header时,不同浏览器的时间格式不一致,有UTC时间和LocalTimeZone之分:
UTC:IE,Firefox,Opera
LocalTimeZone:Chrome,Safari
差异2,
当Http流中没有该Header时,我的第一反应是觉得应该返回null,可惜事与愿违,不同的浏览器返回的东西也有差别,有返回时间初始值和返回当前时间之分:
初始值:Opera
当前时间:Firefox、IE、Chrome、Safari
为了使用上的方便,需要包装掉这些差异,针对各个主要的浏览器实现一个统一的行为。
解决差异1,
可以通过改变Chrome、Safari的时间时区来解决。
解决差异2,
只要跟当前时间对比就可以了?。。。等等不是的,脚本被执行的时间是在页面完成载入的时间之后的,而这个时间差也是很难得到一个确切的值,因为假如判断的脚本是放在脚本文件的话,还要算上页面载入该脚本文件的网络请求的时间开销,就算是硬编码在页面的script标签内,理论也是有一个比较短暂的时间差的,所以这个时间差要自己拿捏好,我的代码中以30秒为时间差,个人觉得这在实际使用中完全可以,这是假设最坏的情况下该脚本在30秒内被执行,而在这30秒内的真实的Last-Modified会被忽略返回null,对一个正常运行的站点来说是不会出现30秒内的Last-Modified的资源的。
以下是代码:
/* * browser */ var ua = navigator.userAgent.toLowerCase(), check = function (r) { return r.test(ua); }, isOpera, isSafari; var browser = { chrome: check(/\bchrome\b/), opera: (isOpera = check(/opera/)), safari: (isSafari = check(/webkit/)), gecko: !isSafari && check(/gecko/), msie: !isOpera && check(/msie/) };
/* * fix the 'lastModified' difference between major browsers */ var lastModified = function (defer) { // when server does not send Last-Modified Header opera provide a minimum datetime value. var time = new Date(document.lastModified); if (time.getTime() === 0) { return null; } // assume that this script will be executed in 30 seconds after the clien page loaded. var now = new Date(), deferTicks = (defer || 30) * 1000; if (browser.chrome || browser.safari) { // chrome and safari use a LocalTime type var offset = -now.getTimezoneOffset(); // unit of minute time = new Date(time.getTime() + (offset * 60 * 1000)); } if (now - time < deferTicks) { return null; } // ret return time.getTime(); } ();
参考文档: