存档Ajax

使用Dojo的ScriptSrcIO

Dojo支持多种的客户端/浏览器传输方式,ScriptSrcIO是其中一种,指利用HTML的script标签来异步加载数据。随着JSON格式的普及,这是一种非常好的方式。

Yahoo的搜索服务可以使用JSON作为响应格式,简单的利用Dojo的ScriptSrcIO来实现。如下:

function yahooSearch() {
var sUrl = “http://api.search.yahoo.com/WebSearchService/V1/webSearch?appid=YahooDemo&output=json&query=ajax”;
var kwArgs = {
url:  sUrl,
mimetype: “text/javascript”,
transport: “ScriptSrcTransport”,
jsonParamName: “callback”,
load: outputResult
};

dojo.io.bind(kwArgs);
}

函数outputResult用来显示结果。

留言

Ajax Patterns 035 - Malleable Content

原文地址:http://ajaxpatterns.org/Microcontent

问题:如何让用户改变内容?

动机:

  • Web不仅仅是提供消息的地方。管理者和一般用户花很多时间在添加和编辑内容上。
  • 所有用户,不管角色如何,都需要知道可以修改什么。
  • 为了鼓励贡献和提升用户体验,编辑应该是简单的。
  • 可编辑的内容页面通常很难看。它们在贡献者和阅读者之间制造了鸿沟,在编辑的时候,很难想象阅读者看到的样子。

解决:Compose the page of “Malleable Content” blocks - small chunks of content that can be edited in-page.

以少量内容的块为单位来组织结构,每个可编辑的区域是分离的。

这样的解决方式已经应用在传统的Web应用中,但是问题是页面的重新加载。重新加载的问题是传统网站有很大的表单的原因之一。这是一种模式(modal)的交互过程,要么编辑要么阅读。

Ajax使得编辑过程更加的平滑。在多数情况下,一个微内容(microcontent)是一个div元素。当该微内容可编辑的时候,另外一个可编辑的div可以被交换进来,或者原来的div变成可以编辑的。另外的一个技巧是使用没有边框的text field和text area,使它们看起来像是只读状态。

决策:

用户如何定位Malleable Content,并打开它进行编辑?

用户需要知道哪些区域是可以编辑的。有两种方式,静态的外观可以提供一些线索;事件处理可以进行进一步的细化。

静态的页面外观使得很容易识别出哪些是可编辑的。很多的做法都是基于Highlight模式的。

  • 增加相继的Malleable Content的间隔。
  • 改变相继的Malleable Content的字体。
  • 为Malleable Content提供不同的背景。
  • 为Malleable Content提供显式的边框。
  • 暴露编辑控件。
  • 在Malleable Content的周围添加标签和辅助信息。

这些都提供了足够的信息,不过这些做法会破坏连续性而且并不适合阅读。另外一个可以依靠的是动态行为。鼠标移动是需要监视的最重要的活动。当鼠标滑过的时候,控件可以改变以声明它们是可编辑的。上面所有的静态线索都可以作为动态线索。比如鼠标滑过Malleable Content的时候改变其背景颜色。

Malleable Content需要标签吗?提供什么样的辅助信息?

很多时候,可以为Malleable Content提供一个显式的名称。名称可以出现在上方和旁边,或是tooltip。

辅助信息可以包括:

  • 创建内容的用户
  • 最后编辑该内容的用户
  • 编辑的次数
  • 创建日期
  • 最后编辑日期

哪些内容将被作为Malleable Content?Malleable Content可以有多大?

任何可以编辑的信息都可以包括在Malleable Content中。如果某些数据的组合是无效的,最好让用户一次编辑所有的数据。Malleable Content应该足够大,从而形成内容上紧密联系的单元。最好足够小,从而编辑的时候不需要滚动条。

用户如何停止编辑?

有如下的选择:

  • 当失去焦点的时候,内容被保存同时变成只读的。
  • 添加显式的控件,比如保存按钮。

考虑如下:

  • 同一时间是否允许多个Malleable Content可以编辑。
  • 用户需要可以取消编辑。

实例:

留言

Ajax Patterns 034 - Drilldown

原文地址:http://ajaxpatterns.org/Drilldown

问题:用户如何在层次结构中进行选择?

动机:

  • 应用和网站很多都是按照层次结构来安排的。为了浏览,用户需要从一个层次结构中选择页面。
  • 层次结构的浏览应该很快速。

解决:

To let the user locate an item within a hierarchy, provide a dynamic drilldown.

该下钻允许沿着层次结构一直浏览,直到选择某个项目(Item)。在每个层次都有如下类似的元素:

  • 目录-当前层次的一个只读名称。
  • 单个的项目-用户可以选择以结束本次交互。
  • 子目录-用户可以选择以下钻到下一个层次。
  • 向上的导航符-可以上钻一个或多个层次。

典型的应用场景包括在应用的不同部分之间导航,通过浏览候选项目的层次结构来填充某个域。

当用户在层次结构中下钻时,要显示每个层次吗?有3种选择:

  • 把下钻固定在某个范围内。每次用户点击了一个目录,下钻只显示那个目录。它的好处是可以防止页面重新布局。
  • 一次显示所有的层次。每次用户点击了一个目录,扩展下钻的区域来为每个目录增加一个列表。
  • 作为第二个方法的变种, 显示所有的层次,不过子菜单显示在文档的前面。从而菜单实际上变成模式的了。这个方法很类似从Windows的启动菜单中选择程序。

非模式的交互更适合Ajax应用,可以动态更新而不需要页面刷新。

决策:

每次用户下钻的过程中都会向服务端发出调用?

有时候,整个层次结构是一次加载的。另外的时候,目录可以根据需要使用XMLHttpRequest Call来下载。取决于下面两点:

  • 层次结构有多大?越大就越不适合一次加载。
  • 层次结构是否容易变化?如何是的,每次展开目录的时候需要从服务端获取最新的数据。服务端甚至可能根据需要即时生成层次结构数据。

实例:

留言

Ajax Patterns 033 - Cross-Browser Component

原文地址:http://ajaxpatterns.org/Cross-Browser_Component

问题:如何处理跨浏览器的兼容性问题?

动机:

  • Ajax的一个很大的卖点是可移植性,可以在任何平台的浏览器上运行。
  • 市面上有很多的浏览器。
  • 很少有某个浏览器占据足够的市场份额使得你可以把你的应用特定于某个浏览器。有时候,很多开发者选择把平台固定为IE,不过IE的市场份额不断再缩小。
  • 在某些情况下,访问某些技术站点的浏览器类型的分布是很不一样的。比如ajaxpatterns.org 网址的访问来说,Firefox的访问占到47.5%。
  • 不同的浏览器之间的区别很大。有些情况下,某种浏览器不支持某些功能。在另外的情况下,两种浏览器支持相同的功能,但是使用的方式不一样。
  • 虽然W3C制定了相关的规范,但是并没有强制的要求。大多数浏览器总会欠缺某些功能。
  • 跨浏览器兼容性的测试是很耗时间的。
  • 当构建Web应用的时候,总是希望集中精力在业务和应用逻辑上,而不希望被底层的浏览器的特性所干扰。

解决:Create cross-browser components, allowing programmers to reuse them without regard for browser compatibility.

一个跨浏览器组件可以抽象底层浏览器的细节,提供单一的API。

存在很多的库来使得对XMLHttpRequest的调用可以跨浏览器。

决策:

用什么标准来创建跨浏览器组件?

主要有两种方式:

  • 基于版本的行为:行为是基于浏览器的版本。
  • 基于功能的行为:行为是基于检测特定的功能是否存在,尤其是某个属性或方法是否存在。

可以通过navigator对象来检测浏览器版本。可以使用已有的浏览器检测库:TechPatterns’ Javascript Browser & OS Detection或是Webreference’s Javascript Browser Sniffer。直接检测的结果是浏览器可能会说谎。比如Opera可以让用户选择报告成什么类型的浏览器。另外一种做法是检测独有的行为。比如可以用document.all来检测IE。

基于版本检测的好处就是只需要处理几个变量。如果是基于功能的话,就需要处理多种组合。

如何当前浏览器不支持某种功能?

如果浏览器不支持某些功能的话,要么不做任何事情,要么就提供一个自定义的版本。

实例:

留言

Ajax Patterns 032 - Server-Side Code Generation

原文地址:http://ajaxpatterns.org/Server-Side_Code_Generation

问题:如何避免使用HTML和Javascript?

动机:

  • HTML和Javascript是标准浏览器唯一识别的语言。一个Ajax应用应该用这些格式的组合来实现。
  • Ajax应用增加了HTML和Javascript的复杂度。Javascript原先用于简单的应用,比如导航支持和表单验证,现在用来在很多应用中驱动用户交互。
  • 多数Ajax应用有后台支持,很少是用Javascript写的。
  • 很难完全的区分浏览器端开发者和服务端开发者的角色。事实上,通常最好由一个开发者工作在某个功能的垂直切片上。从而在不同的层上工作,而开发环境变化很大。
  • 服务端的开发相比Javascript开发有很大优势。
  • 有时候,对同一个应用需要不同的用户界面。

解决:Automatically generate HTML and Javascript from server-side code.

使用某种服务端的语言来编写,然后把它转换成HTML和Javascript。

对于这种模式的一些肯定的看法:

  • 开发者不需要了解HTML和Javascript。该模式使得开发者只需要关注于服务端语言。
  • 框架可以透明的处理浏览器的版本等问题。
  • 框架理论上可以发布多个平台的版本。

代码生成会损害可用性。

下面是一些反对该模式的看法:

  • 随着Ajax的发展,Javascript也在经历复兴,越来越多的Javascript的框架和工具也不断出现。
  • 浏览器端程序也可以实现透明的处理浏览器的版本问题。
  • 把单一的代码转换到不同的平台的想法虽然很早就实现了,但是需要适合每个平台各自的惯例也不是一件容易的事情。

实例:

留言

Ajax Patterns 031 - Predictive Fetch

原文地址:http://ajaxpatterns.org/Predictive_Fetch

问题:如何使得系统快速的响应用户的活动?

动机:

  • 应用应该快速的响应用户的动作,理想情况下应该是即时的。
  • 很多用户活动需要服务端的响应。
  • 由于数据传输和服务端处理的开销,服务端的响应是有很大延迟的。

解决:Have the browser anticipate likely user actions and call the server in preparation.

任何时刻都可能有大量的应用相关的用户活动会发生。有些用户活动会触发对服务端的远程调用,延迟就会很显著。从可用性的角度出发,应用应该让用户觉得那些响应是即时的。也就是说响应时间要在10毫秒以下。不过这显然是不现实的。

即时响应背后的动机就是吞吐量。延迟的最坏影响就是它导致的分心。用户集中在一个任务上,延迟会使得注意力分散。另外的一个问题是会使得用户觉得很沮丧。

预取尝试去掉对某些特定的用户动作延迟。不可能对所有的动作都预取结果,设计者应该很谨慎的考虑预取的动作。通常这些动作是很可能会发生的。另外有些动作不太可能经常发生,但是对于应用很关键的,也需要预取。

预取会导致古怪的行为。用户可能会奇怪有的动作能够很快的响应,而有些则不行。

决策:

应该预取多少信息?

预取是有代价的。预测用户动作是猜测游戏,每次猜错都会浪费资源。

 是浏览器还是服务端来预测用户动作?

服务端和浏览器都可以执行预测。服务端做预测的话,浏览器可以定期执行查询,服务端把信息推送给浏览器。

可以利用什么信息来预测用户动作?

可以利用现在和过去的信息来预测未来,这些信息包括:

  • 用户的资料:用户的资料和历史记录可以提供很好的线索。
  • 用户当前的动作:通常可以从用户的当前的动作中判断下一步他会做什么。
  • 其他用户的活动:一批用户可能执行相同的行为。
  • Collaborative Filtering:一个复杂的技术是根据资料和历史记录把用户关联起来。详细资料高度关联的用户的行为是会相似的。

实例:

留言

Ajax Patterns 030 - Multi-Stage Download

原文地址:http://ajaxpatterns.org/Multi-Stage_Download

问题:如何优化下载的性能?

动机:

  • 内容的下载是需要时间的,尤其包含了大量图片的时候。
  • 用户很少需要阅读页面上的所有内容。
  • 用户为了定位一个特定的项目,通常需要点击多次。
  • 用户有时候通过页面之间的链接来浏览。

解决:Break content download into multiple stages, so that faster and more important content will arrive first.

很多情况下,应用需要从服务端下载很多内容。尤其是启动和发生较大的上下文切换的时候。如果使用一个XMLHttpRequest Call来获取内容的话,只有当所有的内容都处理完毕之后响应才能完成。这就有造成性能瓶颈的危险。

解决的办法是发出多个XMLHttpRequest Calls。虽然从服务端获取的是同样数量的数据,但是处理和传输是并行的。通常,一个页面被划分成多个占位符,每个占位符的内容都是独立下载的。

Multi-Stage Download对传统的Web应用尤其有用,一般的Ajax应用通常只有一个页面。但是如果Ajax应用提供的功能很复杂的话,也要考虑这种方式。

需要注意的是同时发出的请求数是有限制的。这时可以考虑使用Multiplex Call。确定一个浏览器和服务端的协议,浏览器封装多个请求,服务端封装多个响应。从而,只在一个请求中包含所有所需的数据,最初的响应可能只返回很少的结果。浏览器等待一会,继续请求其他数据。

决策:

页面如何划分成块?

建议为初始的内容构建较小的块使得初次下载的速度较快。把同时准备好的数据分成同一个组中。过多的块会使得页面很难看,甚至可能使得已经显示出来的块到处移动。

如何组织页面结构?

使用基于CSS的布局可以使得页面的结构不至于发生大的变化。

 下载的内容的格式如何?

HTML的或者语义内容都可以。

 当内容正在下载的时候,块如何展示?

整个DOM结构可以在页面初次下载的时候就建立好。对于后来加载的内容使用DIV或其他结构来做占位符。最后在块中增加进度指示器。

也可以动态的构造DOM。

调用是同时发生的吗?

记住浏览器同时发出的请求是有限的。通过使用Javascript的setTimeout,延迟加载一些比较次要的内容。

实例:

留言

Ajax Patterns 029 - Guesstimate

原文地址:http://ajaxpatterns.org/Guesstimate

问题:如何减少对服务端的调用?

动机:

  • To comprehend system activity and predict what might be happening next, it’s useful to have frequent updates from the server.
  • 持续从服务端更新的代价很昂贵。

解决:Instead of requesting information from the server, make a reasonable guess.

Guesstimate是基于历史数据的。浏览器可以有多种途径来获取这些信息:

  • Ajax应用一启动就可以积累相关的信息。
  • 长期的数据可以保存在cookie中,以供下次会话的时候使用。
  • 服务端可以提供历史数据,浏览器有疑问的时候可以查询。

使用历史数据,就可以推测未来的事件,尽管不太精确。

决策:

真实数据多久获取一次?多久做一次Guesstimate?

大多数的Guesstimate是在获取真实数据之间进行的。guesstimate的目的在于减少获取真实数据的频率,所以需要确定一个实际的频率。如果准确性很重要的话,真实数据需要很快的获取;如果服务端和带宽资源更重要的话,就尽可能少的访问。

多久计算一次新的Guesstimate?Guesstimate通常都需要数学计算。太多的计算会损害性能,太少的计算又失去了Guesstimate的意义。

Guesstimate如何与真实数据融合在一起?

每次真实的数据到达时,Guesstimate的数据需要与真实数据结合在一起。最简单的办法是丢弃Guesstimate,使用真实的数据直到需要下一次的Guesstimate。有时候需要更加复杂的做法。Apple的ITunes的计数器会故意的过低估计下载数量。所以当真实的数据到达时,数字总是上升的。

用户是否知道使用了Guesstimate?

当使用Guesstimate的时候,用户会注意到一些奇怪的事情。当应用把数据从Guesstimate切换到服务端的真实数据时,可能数值会有一个突然的变化。这会使得用户失去对应用的信任。

 服务端需要提供什么样的支持?

有时候,服务端提供浏览器做Guesstimate时需要的信息。需要考虑什么样的计算对浏览器来说是合适的,并且它也能获取这些信息。

实例:

  • Apple ITunes Counter
  • GMail Storage Space

留言

Ajax Patterns 028 - Browser-Side Cache

原文地址:http://ajaxpatterns.org/Browser-Side_Cache

问题:系统如何快速的响应用户的活动?

动机:

  • 应用应该快速响应用户的活动,理想情况下是即时的。
  • 许多用户动作需要服务端的响应。
  • 由于数据传输和服务端处理的开销,从服务端来的响应通常都是延迟的。

解决:Retain server results in a browser-side cache.

缓存保存查询-结果对:查询是缓存中的键,服务端的结果是对应的值。当浏览器执行XMLHttpRequest Call的时候首先检查缓存,如果存在对应的值,就使用缓存里面的值作为结果。

键和值应该是什么格式的?最简单的情况下,键可以是URL地址,而值就是响应体。在其他情况下,键和值可能代表更高层次和语义上的内容。这是设计上的决策。

一个缓存的数据结构需要能够随机的访问键-值对。在Javascript中,缓存可以直接用associative array来创建。

可以把缓存看成一个代理,Proxy模式的一个应用。

XMLHttpRequest的异步特性增加了一点复杂度。通常情况下,一个缓存的ResultFetcher以同步的方式返回结果,不管结果是否在缓存中。但是在Ajax应用中,只有当缓存中找到结果的时候才能这么做。否则服务端的响应会在获取方法已经返回之后的某个时间传送回来。你可以考虑让请求者给获取方法传送一个回调函数。从而获取方法不直接返回任何结果,却保证总是使用需要的值调用回调函数。

决策:

用什么来存储键和值?

最简单的情况是URL和响应体。如果遵循RESTful Service的规范的话,这种方法很有效。它把缓存机制和应用完全隔离开。不过这种方式会带来很大的开销。可以考虑语义相关的值。

如何控制缓存的大小?

可以通过确定缓存的容量以及达到容量时删除缓存项的方式来控制缓存的大小。通常的算法有LRU和LFU。

如何防止过时数据的影响?

有一些办法:

  • 为每个缓存中的项增加一个时间戳。当获取一个项的时候,根据时间戳来判断是否过时。
  • 调度一个周期性的循环来删除过时数据。
  • 实现一个浏览器和服务端的协议来允许浏览器判断缓存项是否过时。浏览器可以对每个项保存时间戳,服务端接收时间戳来判断是否过时。时间戳的另外一种选择是hash函数。
  • 服务端实现一个服务来发布已经发生的变化。使用Periodic Refresh来监听这些变化,从缓存中删除变化的项。

实例:

  • libXmlRequest

留言

Ajax Patterns 027 - Fat Client

原文地址:http://ajaxpatterns.org/Fat_Client

问题:How can you architect the system to feel truly rich and interactive?

动机:

  • 应用应该尽快的响应用户的动作,最好是即时的。
  • 由于数据传输和服务端处理的开销,服务端的响应是会延迟的。

解决:Create a rich, browser-based, client by peforming remote calls only when there is no way to achieve the same effect in the browser.

该模式认为有些应该把一部分的应用逻辑和业务逻辑放在浏览器中。

决策:

业务和应用逻辑如何在浏览器中实现?

由于要在浏览器中实现业务和应用逻辑,对Javascript的使用有了更高的要求。下面是一些有用的提示:

  • Javascript是一种独特的语言,有自己的特征和使用模式。注意不要把服务端语言的体系结构概念滥用在Javascript上。
  • 如果你熟悉Java或C#语言,花点时间了解dynamic typing并学会去适应它。
  • 谨慎的使用面向对象编程的思想。Javascript使用prototype-based paradigm,可以达到类似类定义和继承的效果。
  • 对于复杂的功能,考虑使用单元测试框架。
  • Javascript运行较慢,所以优化是很重要的。考虑内存使用问题以及可能导致内存泄漏的浏览器专用的bug。
  • 把复杂的应用拆分成多个Javascript文件。考虑使用On-Demand Javascript来管理。
  • 尽可能的复用。

数据如何持久化?

可以使用cookie来保存数据,不过重要的数据需要保存在服务端。整个应用可能运行在浏览器中,但是必须要有数据传输机制。对一个Fat Client来说,Submission Throttling是最好的选择。当用户再次登录的时候,另外一种方法可以用来把信息获取下来,比如Multi-Stage Download

实例:

  • NumSum
  • GMail
  • DHTML Lemmings
  • JS/Unix Shell

留言

« Previous entries