分类:
2009-06-17 16:30:44
浏览器中的是应用而不是内容
在传统的基于页面的web应用中,浏览器扮演着哑终端[7]的角色。它对用户处于操作流程哪一阶段一无所知。这些信息全部都保存在服务器上,确切地说,就是在用户会话上。时至今日,服务器端的用户会话早已是司空见惯。如果你使用java或者.net编程,服务器端的用户会话更是标准API的一部分——还有Request、Response、MIME类型——没有了它们简直不可想象。图1-11描绘了传统Web应用典型的生命周期。
当用户登录或者以其他方式初始化一个会话时,系统会创建几个服务器端的对象。例如,电子商务类型的网站需要创建表示购物车以及用户身份证明的对象。同时将浏览器站点的首页呈现给用户,这个html标记的数据流由模板文件以及特定于该用户的数据和内容(例如该用户最近浏览的商品列表)组成。
用户每次和服务器交互,都会获得另一个文档。在这个文档中,除了特定于该用户的数据以外,包含的其他模板文件和数据都是相同的。浏览器总是忠实地丢弃掉老的文档,显示新的文档,因为它是哑终端,而且也不知道还可以做些什么。
当用户选择退出或者关闭浏览器的时候,应用退出,会话消失。这个时候持久层会把用户下次登录后需要显示的信息存储起来。Ajax则不同,它把一部分应用逻辑从服务器端移到了浏览器端,图1-12描绘了这一情况。
图1-11 传统Web应用的生命周期。用户和应用会话的所有状态都保留在Web服务器上。用户在会话中看到的是一系列的页面,每次页面切换都不可避免地要到服务器上走一个来回
图1-12 Ajax应用的生命周期。用户登录后,服务器交付一个客户端应用给浏览器。这个应用可以独立处理很多的用户交互,对于自己无法独立处理的交互,应用会以后台方式发送请求给服务器,而不会打断用户的操作流程。
用户登录的时候,服务器交付给浏览器一个复杂得多的文档,其中包含大量的javaScript代码。这个文档将会在整个会话的生命周期内与用户相伴。在这一过程中,随着用户与其交互,它的外观可能会发生相当大的变化。它知道如何响应用户的输入,能够决定对于这些请求,是自行处理还是传递给web服务器(Web服务器再去访问数据库或者其他资源),或者通过两者结合的方式进行处理。
因为这个文档在整个用户会话中都存在,所以它可以保存状态[8]。例如,购物车的内容可以保存在浏览器中而不是服务器的会话中。
服务器交付的是数据而不是内容
我们已经提到,在传统的Web应用中,服务器在每个步骤都需要把模板文件、内容和数据混合发送给浏览器。但实际上,当向购物车中添加一件物品的时候,服务器真正需要响应的仅仅是更新一下购物车中的价格。如图1-13所示,这只是整个文档中极小的一小部分。
基于ajax的购物车可以向服务器发起一个异步请求来完成这件事,这样做显得更聪明。模板文件、导航列表和页面布局上的其他部分已经随着初始页面发送给了浏览器,服务器无需重发,以后每次只需要发送相关的数据就可以了。
Ajax应用可以通过多种方式来做这件事情。例如,返回一段JavaScript代码、一段纯文本或者一小段XML文档。这些方式各自的优缺 点,我们将留到第5章再详细考察。但是,毫无疑问的是,无论返回数据采用何种格式,这些方式所传输的数据量都要比传统的Web应用中一股脑返回一个大杂烩 的方式少得多。
在Ajax应用中,网络的通信流量主要是集中在加载的前期,无论如何,用户登录后是需要一次性地将一个大而复杂的客户端交付给浏览器。但是在此 之后,与服务器的通信则会有效率得多。对于瞬态应用来说,积累起来的通信流量要比以前的基于页面的Web应用少很多。与此同时,平均的交互次数则有所增 加。整体而言,Ajax应用的带宽消耗要比传统的Web应用低一些。
用户交互变得流畅而连续
浏览器提供了两种输入机制:超链接和HTML表单。
超链接可以在服务器上创建,并预加载指向动态服务器页面或者servlet的CGI参数。可以用图片或者CSS(层叠样式表)来装饰超链接,并且当鼠标停在上面时还可以提供基本的反馈。经过合理设计,超链接可以变成一个很有想像力的UI组件。
表单则提供了桌面应用的一组基础UI组件:输入文本框、单选按钮和多选按钮,还有下拉列表。但仍然缺少很多有用的UI组件,例如,没有可用的树控件、可编辑的栅格、组合输入框等。表单像超链接一样,也指向服务器的一个URL地址。
图1-13 细分服务器发送的内容,(A)是传统的web应用,(B)是ajax应用。(C)表示随着应用使用时间的延长,累积的网络流量的增长情况
超链接和表单也可以指向javaScript函数。这一技术通常用在将数据提交给服务器之前对表单输入进行简单的校验,如检验是否有空值,数值是否越界等等。这些JavaScript函数的生存期和页面本身是一致的,当页面提交之后,这些函数也就不存在了。
当一个页面已提交而下一个页面还没有显示出来的时候,用户实际上处于没人管的状态。老的页面还要显示一会儿,浏览器甚至还会允许用户点击一些链 接。但这些点击可能会导致一些不可预料的结果,甚至破坏服务器端会话的状态。用户通常应该等到页面刷新完成,当然也可以选择在刷新完成之前就在新页面上做 一些操作。例如,当页面只显示了一部分时从中选择一条裤子放进购物车不大可能会造成什么破坏(例如,不会修改顶级的服装分类:男装、女装、童装、配饰)。
我们继续看这个购物车的例子。ajax的购物车是通过异步方式发送数据的,用户可以很快地把东西拖进来,就像点击一样快。只要客户端购物车的代码足够健壮,它可以很轻松地处理这样的负载,而用户则可以继续做他想做的事。
要知道,在服务器端并没有一个真正的购物车等着装东西,只有会话中的一个对象而已。购物的时候,用户并不想知道会话对象,购物车对于用户而言是 一个较恰当的比喻,用现实世界中熟悉的概念来描述这里发生的事情。对于用户来说,如果强迫他们去理解计算机领域中的术语,只会让他们远离网站。等待页面的 刷新,一下子就把用户从愉快的使用体验中拽了出来,让他感觉到自己所面对的只不过是一台冰冷的机器罢了(图1-14)。使用Ajax来实现这些应用则可以 避免这些令人不快的体验。当然了,在这个例子中的购物只是一个瞬态活动。考察一下其他的业务领域,例如,一个业务量很大的帮助中心或者一项复杂的工程任 务,如果因为需要等待页面刷新而将工作流程打断几秒钟[9],那肯定是不可接受的。
图1-14 处理事件打断了用户的工作流程。用户要处理与业务相关的和与计算机相关的两种对象。这迫使用户频繁地在这两者之间切换,从而导致用户注意力分散,工作效率降低
Ajax的另一个好处是,我们可以对丰富的用户操作事件进行捕获。类似于拖拽这样的复杂UI概念也不再是遥不可及的。这使得web应用的UI体验可以全面提升到近乎与桌面应用的UI组件相媲美的高度。从可用性的角度来看,这很重要,不仅仅是因为它释放了我们的想象力,而且也是因为它可以将用户交互和服务器端的请求更加充分地混合起来。