AJAX应用有能力使得(我们)通过后台的HTTP连接获取小批量的信息,这是现代浏览器API必须装备的强大的工具。对于大多数的浏览器(例如,Firefox 1.5,Safari 2.0,Opera 8.5),这个任务背后的引擎是Windows对象的 XMLHttpRequest (XHR)对象。Internet Explorer 5.5-6对于这个对象有不同的表述,例如, XMLHttp,但是IE 7有可能采用与其他浏览器相同的对象。
避免混乱
然而,在AJAX应用中混乱的使用HTTP请求从来就不是一个好的注意或者说好的设计决策。服务器端相对应的对象没有能力处理如潮水般的请求,而AJAX应用的客户端可能会有一些请求的超时或者中断,这会破坏用户体验,而用户体验却恰恰是AJAX的强大之处。
能源价格
我在最近的一篇文章里介绍的一个应用使用XHR来获得最新的石油、汽油和其他的能源的价格。这些数据,由美国能源信息秘书处发布,都是一些公开的领域。我的应用就是把它们从适当的网址获取或者挖出。更好的办法是和能源的Web服务连接(HTML的挖掘是笨拙和脆弱的),但是我没有找到一个开源的、免费的服务。我公开建议这样的服务。
EIA的Web页面满足了应用的目的,因为它毕竟是提供石油期货的最新数据。当用户登陆Web页面的时候,应用在浏览器窗口显示价格。图1-1显示了页面左边的样子。左边栏显示的是价格,这些价格当鼠标经过的时候会加亮。
图1-1:获取能源价格的Web页面的样子。(点击看大图)
页面上每一个区域或 div标签都专注于一个独立的价格(例如石油),它们都有单独的刷新按钮。这赋予了用户获取最新价格的选择权。然而,EIA一个礼拜只将这些价格更新一次。因而,如果一个用户在一个小时之前已经登陆过了,再为处理这些请求而到EIA网页将是极大浪费。我们知道,这个价格在很大程度上是一样的,所以我们必须让当前显示的价格驻留下来。
为缓存数据指定一个时间期限
有大量的可行的方案来解决这一个问题或需求。我所选择的一个解决方案是,使用原型开源JavaScript库,创建一个对象。当一个价格被HTTP请求最新更新以后,保持它的轨迹。这个对象用一个属性来表示一个范围,例如24小时。如果一个价格在小于24小时之前被获取过,那么这个对象阻止请求被初始化,并且显示相同的数据。
这就是一个AJAX的缓存策略,它被设计来周期性的从服务器刷新数据,更新的条件是仅仅在客户端数据的版本被缓存了一个给定的周期以后。如果应用的用户离开了她的浏览器的页面超过24小时,这时她点击刷新按钮,XHR发送请求并且取得一个新的价格来显示。我们希望给与用户刷新价格而不用重新载入整个页面的能力,而且我们也希望砍掉那些不必要的请求。
引入JavaScript
Web应用在HTML文件里使用 script标记来引入必要的JavaScript,包括原型库(Prototype library)。我写的第一篇关于这个应用的xml.com文章展示了怎么下载和安装原型(Prototype)
<head>...
<script src="http://www.eeviewpoint.com/js/prototype.js" type="text/javascript">
</script>
<script src="http://www.eeviewpoint.com/js/eevpapp.js" 
type="text/javascript">
</script>
..</head>
创建刷新按钮
首先,我展示来自 eevapp.js的代码,它们被我用来获取能源价格。其次,我将展示这个对象,它就像一个请求过滤器。
//When the browser has finished loading the web page,
//fetch and display the energy prices
window.onload=function(){
 //generatePrice method takes two parameters:
 //the energy type (e.g.,oil) and the id of the
 //span element where the price will be displayed
 generatePrice("oil","oilprice");
 generatePrice("fuel","fuelprice");
 generatePrice("propane",
 "propaneprice");
 
//set up the Refresh buttons for 
//getting updated oil,gasoline,and 
//propane prices.
 //Use their onclick event handlers. 
$("refresh_oil").onclick=function(){ 
generatePrice("oil","oilprice"); }
 $("refresh_fuel").onclick=function(){ 
generatePrice("fuel","fuelprice"); }
 $("refresh_propane").onclick=function(){ 
generatePrice("propane",
 "propaneprice"); }
 
};
代码的注释解释了这段代码的功能,那些奇数的语法片断中需要解释的是 $("refresh_oil").onclick形式的表达式。
原型(Prototype)使用 $()方法来返回一个文档对象模式(DOM)的 Element对象。 Element和HTML的id属性相关联,代码给 $()方法传递一个 string参数。这个语法和 document.getElementById("refresh_oil")是等价的,但是它对于开发者来说却更短、更加容易上手。 "refresh_oil"指的是什么呢?它是Web页面上的刷新按钮的 id。参见图1-1所显示的浏览器上的左边栏的刷新按钮。
<input type="submit" id="refresh_oil" .../>
代码给按钮的 onclick事件处理器设置了一个方法,它用来选择性的获取一个新的能源价格。选择性的意思是,我们的过滤器决定是否发送一个HTTP请求。
首先是检测 CacheDecider 对象
generatePrice()方法首先检测一个叫 CacheDecider的缓存关联对象,用来决定是否初始化一个新的用来获取能源价格的HTTP请求。每一个能源类别——石油、汽油和丙烷,都拥有自己的 CacheDecider对象。代码在一个叫 cacheHash的hash里存储这些对象。因此,表达式 cacheHash["oil"]将会返回石油价格的 CacheDecider对象。
如果 CacheDecider或者过滤器允许代码创建一个新的HTTP请求( CacheDecider.keepData()返回 false),那么代码将调用 getEnergyPrice()来更新,即,原油价格。代码的注释解释了代码的功能。
/*Check the CacheDecider object to determine
if a new energy price should be fetched*/
function generatePrice(energyType,elementID){
 //set the local variable cacher to the CacheDecider
 //object associated with oil,gas,or propane
 var cacher = cacheHash[energyType];
 //If this object is null,then a CacheDecider object
 //has not yet been instantiated for the
 //specified energy type.
 if(! cacher) {
 //CacheDecider has a parameter that
 //specifies the number of seconds to keep
 //the data,here 24 hours
 cacher = newCacheDecider(60*60*24); 
//store the new object in the hash with
 //the energy type,say "oil",as the key
 cacheHash[energyType]=cacher;
 //Fetch and display the new energy price
 getEnergyPrice(energyType,elementID);
 return;
 }
 //The CacheDecider has already been instantiated,so
 //check whether the currently displayed energy price
 //is stale and should be updated.
 if(! cacher.keepData()) { 
getEnergyPrice(energyType,elementID);}
}
/*
Use Prototype's Ajax.Request object to fetch an energy price.
Parameters: 
energyType is oil,fuel,or propane.
 is the id of a span element on the web page;elementID
the span will be updated with the new data.
*/
function getEnergyPrice(energyType,elementID){
 
new Ajax.Request(go_url,{method: "get",
 parameters: "priceTyp="+energyType,
 onLoading:function(){ $(elementID).innerHTML=
 "waiting...";},
 onComplete:function(request){
 if(request.status != 200) {
 $(elementID).innerHTML="Unavailable."
 } else {
 $(elementID).innerHTML=
 request.responseText;}
 }});
 
}
原型的Ajax对象
与AJAX相关的代码使用原型的 Ajax.Request对象,只有10行代码长。代码和服务器相连,从美国政府网站上取得新的能源价格。然后显示这些价格,而不用改变Web页面的其他部分。然而,代码有点容易混淆,这儿是解释。
你可能习惯于寻找被直接编程的 XMLHttpRequest对象,然而,原型(Prototype)为你初始化了这个对象。包括针对各种浏览器需要做的处理。仅仅是产生一个新的AJAX对象,像新的 Ajax.Request。设置HTTP请求的动作。 prototype.js文件里包括了这个对象的定义。由于我们的Web页面引入了JavaScript文件,我们能够创建这个对象的一个新的实例,而不用越过其他的任何hoop。我们的代码不用处理XHR涉及的各种浏览器的不同。
Ajax.Request的第一个参数是它需要连接到的服务器组建的URL。例如 http://www.eeviewpoint.com/energy.jsp。第二个参数指出这是一个 GET HTTP类型请求。第三个参数提供了一个将要传递到服务器组件的查询串。因而,整个URL看起来像这样的样子: http://www.eeviewpoint.com/energy.jsp?priceTyp=oil,例如。
进度指示器
另外的一对参数用来让代码开发者决定在一个不同的请求处理情形下,应用该怎么做。例如, onLoaded代表的是这样一个请求序列的情形:当 XMLHttpRequest.send()方法被调用的时候,一些HTTP响应头被获得,同时也有HTTP的响应状态。在这个情形下,我们的应用显示“等待…”,一个新的价格将随后出现。 onComplete代表的是能源价格请求完成时的情形。这个方法和 onComplete关联起来,因此,它决定了将会对请求的返回值做什么操作。代码自动的提供这些方法,它的request参数代表XHR使用HTTP request的一个实例。
onComplete:function(request){...
因此,在这个例子中,代码通过语句 request.responseText取得返回值。如果一切正常,这个属性将要返回一个新的价格,例如66.07。
Ajax.Request对象也允许代码基于特定的HTTP响应状态值做出一定的动作。这是通过检测XHR的状态属性完成的( request.status)。如果状态值不是200(例如,可能是404,这是“Not Found”的意思),这个值表示响应是成功的,那么应用就在能源价格显示的地方显示“unavailable”。
我们也可以改变上面的行为,使得如果是一个不成功的请求的话,仅仅让当前显示的价格不变。
new Ajax.Request(go_url,
 onLoading:function(){ $(elementID).innerHTML=
 waiting...";},
 onComplete:function(request){
 if(request.status == 200) {
 $(elementID).innerHTML=
 request.responseText;}
}});
CacheDecider对象
最终价格的客户端难点是CacheDecider对象,图1-2是描述这个对象的UML图,我使用原型(Prototype)库写出了这个JavaScript对象。
图1-2, CacheDecider的UML类图描述
下面是这个对象的代码,在 eevapp.js文件中:
var CacheDecider=Class.create();
CacheDecider.prototype = {
 initialize: function(rng){
 //How long do we want to
 //keep the associated data,in seconds?
 this.secondsToCache=rng;
 this.lastFetched=new Date();
 
 },
 keepData: function(){
 var Now = new Date();
 //Get the difference in seconds between the current time
 //and the lastFetched property value
 var secondsDif = parseInt((Now.getTime() - 
this.lastFetched.getTime()) / 1000);
 //If the prior computed value is less than
 //the specified number of seconds to keep
 //a value cached,then return true
 if (secondsDif < this.secondsToCache){ return true;}
 //the data in the cache will be refreshed or re-fetched,
 //therefore reset the lastFetched value to the current time
 this.lastFetched=new Date();
 return false;
 }
}
prototype.js文件中包含了一个对 Class的对象定义,调用 Class.create()返回一个包含 initialize()方法的对象,这像其他语言的构造器方法。JavaScript在代码每一次调用一个相关对象的新的实例的时候,都会调用这个方法。
我们的 CacheDeciderinitialize()方法初始化了两个属性: secondsToCache,它代表在被缓存的值的下一个值被获取到之间的以秒为单位的时间数量。 lastFetched,它代表的是,无论被缓存对象什么时候有了更新,最后一次更新的被缓存值的JavaScript的 Date对象。
CacheDecider没有保存一个被缓存对象的引用。其他的对象使用 CacheDecider来存储和检测时间限制或范围。
如果你还不清楚,请查阅副标题为“Check the CacheDecider Object Firs”的解释。
CacheDecider里还有一个 keepData()方法,这个方法决定,在由于 lastFetched超过缓存值所定义的时间段,是否这个过去的时间数被支持保留。
在我们的应用中,我们保持能源价格值在24小时之内,直到它被一个HTTP请求刷新。
cacher = new CacheDecider(60*60*24);
如果这个时间段没有被超过,那么 keepData()返回true。否则, lastFetched属性被重新设置到当前时间(由于缓存值现在不能通过HTTP请求被更新),并且方法返回false。
用户能够更新数据,无论什么时候,只要她想这样,他只需重新载入整个web页面。这个动作将重新初始化我们所讨论到的所有对象。
服务器组件
应用使用了一种叫做“cross-domain proxy”的模式,这在 http://ajaxpatterns.org/Cross-Domain_Proxy相关网站上有讨论。即使我的应用是从U.S. EIA网页上获取信息,这种获取由一个源自相同域( eeviewpoint.com)的组件初始化,然后作为我们应用的web页面。
获取web页面信息的服务器组件可以选择你的语言来编写:PHP,Ruby,Python,ASP.NET,Perl,Java。我选择Java,servlet/JSP编程和Tomcat容器。 Ajax.Request对象和JSP相联接,使用Java工具类从U.S. EIA网站上获取能源信息。请参阅“Resources”栏,以便知道从哪里得到我们所讨论的那些类。
资料
Prototype:
http://script.aculo.us/
JavaScript code: http://www.parkerriver.com/ajaxhacks/xml_article_js.zip
Java code:
http://www.parkerriver.com/ajaxhacks/xml_article_java.zip

一个AJAX的缓存策略的更多相关文章

  1. 详解使用双缓存解决Canvas clearRect引起的闪屏问题

    这篇文章主要介绍了详解使用双缓存解决Canvas clearRect引起的闪屏问题的相关资料,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  2. 利用Node实现HTML5离线存储的方法

    这篇文章主要介绍了利用Node实现HTML5离线存储的方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  3. HTML5 Web缓存和运用程序缓存(cookie,session)

    这篇文章主要介绍了HTML5 Web缓存和运用程序缓存(cookie,session),小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  4. 详解前端HTML5几种存储方式的总结

    本篇文章主要介绍了前端HTML5几种存储方式的总结 ,主要包括本地存储localstorage,本地存储sessionstorage,离线缓存(application cache),Web SQL,IndexedDB。有兴趣的可以了解一下。

  5. 在iOS上,缓存绘制的屏幕图像并显示它的最快方法是什么?

    我没有让drawRect每次重绘数千个点,我认为有几种方法可以“在屏幕上缓存图像”和任何其他绘图,我们将添加到该图像,并在drawRect时显示该图像:>使用BitmapContext并绘制到位图,并在drawRect中绘制此位图.>使用CGLayer并在drawRect中绘制CGLayer,这可能比方法1快,因为此图像缓存在图形卡中(并且它不会计入iOS上“内存警告”的RAM使用情况?

  6. ios – NSURLCache和数据保护

    我正在尝试保护存储在NSURLCache中的敏感数据.我的应用程序文件和CoreDatasqlite文件设置为NSFileProtectionComplete.但是,我无法将NSURLCache文件数据保护级别更改为NSFileProtectionCompleteUntilFirstUserAuthentication以外的任何其他级别.这会在设备锁定时暴露缓存中的任何敏感数据.我需要缓存响应,以

  7. iOS Safari多久会清除一次缓存?

    我使用移动Safari缓存来存储我想要持久化的一些数据,所以我希望它们能够在Safari重启和iOS重启后继续存在.但是我已经阅读了somenew和someold报告,Safari在Safari重新启动时清除了它的缓存.但我对Safari8.3的非科学测试表明,有时这个缓存实际上不仅可以在应用程序重启后生存,而且甚至可以重启iOS(!).所以我在这一点上有点困惑.iOSSafari缓存清除的规则是否记录在某处?你们中有谁知道他们并且可以向我解释他们吗?解决方法希望有人发现我错了但是……

  8. 通过AFNetworking 2.0上传iOS图像

    我一直在寻找新的AFNetworking2.0上传图像的例子.但是我正在撞墙,无法弄清楚代码有什么问题.所以这是我使用的代码TIA解决方法我最终使用了多部分请求

  9. ios – 在Objective-C中发送分块的HTTP 1.1请求

    我有以下问题:我正在创建一个非常大的SOAP请求(数据是一个编码为Base64字符串的视频),因此我不能将其作为原始SOAP请求发送,而是需要在HTTP1.1块中发送它.我似乎无法弄明白该怎么做.我在这里使用了代码:WhatarealternativestoNSURLConnectionforchunkedtransferencoding但它似乎没有做我认为应该做的事情–我可以看到请求作为单个请求

  10. ios – 如何获取缓存图像SDWebImage的数据

    我正在使用SDWebImage库来缓存我的UICollectionView中的Web图像:但我想将缓存的图像本地保存在文件中,而不是再次下载它们有没有办法获取缓存图像的数据解决方法SDWebImage默认自动缓存下载的图像.您可以使用SDImageCache从缓存中检索图像.当前应用会话有一个内存缓存,它会更快,并且有磁盘缓存.用法示例:还要确保在文件中导入SDWebImage.(如果您使用的是Swift/Carthage,它将导入WebImage

随机推荐

  1. xe-ajax-mock 前端虚拟服务

    最新版本见Github,点击查看历史版本基于XEAjax扩展的Mock虚拟服务插件;对于前后端分离的开发模式,ajax+mock使前端不再依赖后端接口开发效率更高。CDN使用script方式安装,XEAjaxMock会定义为全局变量生产环境请使用xe-ajax-mock.min.js,更小的压缩版本,可以带来更快的速度体验。

  2. vue 使用 xe-ajax

    安装完成后自动挂载在vue实例this.$ajaxCDN安装使用script方式安装,VXEAjax会定义为全局变量生产环境请使用vxe-ajax.min.js,更小的压缩版本,可以带来更快的速度体验。cdnjs获取最新版本点击浏览已发布的所有npm包源码unpkg获取最新版本点击浏览已发布的所有npm包源码AMD安装require.js安装示例ES6Module安装通过Vue.use()来全局安装示例./Home.vue

  3. AJAX POST数据中文乱码解决

    前端使用encodeURI进行编码后台java.net.URLDecoder进行解码编解码工具

  4. Koa2框架利用CORS完成跨域ajax请求

    实现跨域ajax请求的方式有很多,其中一个是利用CORS,而这个方法关键是在服务器端进行配置。本文仅对能够完成正常跨域ajax响应的,最基本的配置进行说明。这样OPTIONS请求就能够通过了。至此为止,相当于仅仅完成了预检,还没发送真正的请求呢。

  5. form提交时,ajax上传文件并更新到&lt;input&gt;中的value字段

  6. ajax的cache作用

    filePath="+escape;},error:{alert;}});解决方案:1.加cache:false2.url加随机数正常代码:网上高人解读:cache的作用就是第一次请求完毕之后,如果再次去请求,可以直接从缓存里面读取而不是再到服务器端读取。

  7. 浅谈ajax上传文件属性contentType = false

    默认值为contentType="application/x-www-form-urlencoded".在默认情况下,内容编码类型满足大多数情况。在这里,我们主要谈谈contentType=false.在使用ajax上传文件时:在其中先封装了一个formData对象,然后使用post方法将文件传给服务器。说到这,我们发现在JQueryajax()方法中我们使contentType=false,这不是冲突了吗?这就是因为当我们在form标签中设置了enctype=“multipart/form-data”,

  8. 909422229_ajaxFileUpload上传文件

    ajaxFileUpload.js很多同名的,因为做出来一个很容易。我上github搜AjaxFileUpload出来很多类似js。ajaxFileUpload是一个异步上传文件的jQuery插件传一个不知道什么版本的上来,以后不用到处找了。语法:$.ajaxFileUploadoptions参数说明:1、url上传处理程序地址。2,fileElementId需要上传的文件域的ID,即的ID。3,secureuri是否启用安全提交,默认为false。4,dataType服务器返回的数据类型。6,error

  9. AJAX-Cache:一款好用的Ajax缓存插件

    原文链接AJAX-Cache是什么Ajax是前端开发必不可少的数据获取手段,在频繁的异步请求业务中,我们往往需要利用“缓存”提升界面响应速度,减少网络资源占用。AJAX-Cache是一款jQuery缓存插件,可以为$.ajax()方法扩展缓存功能。

  10. jsf – Ajax update/render在已渲染属性的组件上不起作用

    我试图ajax更新一个有条件渲染的组件。我可以确保#{user}实际上是可用的。这是怎么引起的,我该如何解决呢?必须始终在ajax可以重新呈现之前呈现组件。Ajax正在使用JavaScriptdocument.getElementById()来查找需要更新的组件。但是如果JSF没有将组件放在第一位,那么JavaScript找不到要更新的内容。解决方案是简单地引用总是渲染的父组件。

返回
顶部