首页 新闻 论坛 群组 Blog 文档 下载 读书 Tag 网摘 搜索 开源 FAQ 第二书店 博文视点 程序员
频道: 研发 数据库 中间件 信息化 视频 .NET Java 游戏 移动 服务: 人才 外包 培训
    图书品种:235680
       
热门搜索: ASP.NET Ajax Spring Hibernate Java

AJAX 历史记录问题的处理

文/陈英

AJAX技术作为Web2.0的标志技术,其良好的用户体验、优良的设计模式、众多浏览器厂家的广泛支持,正日益受到人们的关注和学习。

从本质上说AJAX(Asynchronous JavaScript And XHTML)并不是新技术,它描述了JavaScript、DOM、CSS、XHTML等一组技术,使浏览器可以为用户提供更为自然的浏览体验。在AJAX之前,Web站点强制用户进入提交/等待/重新显示循环,用户的动作总是与服务器的响应时间同步。AJAX提供与服务器异步通信的能力,从而使用户从请求/响应的循环中解脱出来。借助于AJAX,可以在用户单击按钮时,使用JavaScript和DHTML立即更新UI,并向服务器发出异步请求,以执行服务器后端操作。当请求返回时,就可以使用JavaScript和CSS来相应地更新UI,而不是刷新整个页面。最重要的是,用户甚至不知道浏览器正在与服务器通信:Web站点看起来是即时响应的。例如:gmail中邮件撰写过程中邮件草稿的自动保存;国内优秀的Web2.0网站抓虾(www.zhuaxia.com)几乎全站采用AJAX交互方式。

但正由于AJAX的异步特征,使得历史记录的保存上存在问题。目前的浏览器历史记录是基于传统同步请求响应的,不同的URL对应不同的页面,每次页面操作在URL变化的同时整个页面也产生改变;而AJAX异步请求异步响应,页面操作往往只刷新部分页面UI,同一个URL可能对应于不同的请求和页面响应,在浏览器前进、后退及刷新等浏览器历史操作中,浏览器不能根据URL准确地发出历史页面的请求,用户也就不能得到正确的页面响应,影响用户体验。

笔者在学习、使用AJAX的基础上,找到了解决这一问题的方法,其基本思想是:不依赖于浏览器而通过编码记录历史页面请求;在浏览器历史浏览操作中,先找到历史页面请求,再重新执行这些请求来达到正确浏览历史页面的作用。其具体实现方案有以下两种:

函数法

采用这韩书法有一个前提,需要页面是通过某个JavaScript函数的执行而得到。在这样的前提下,把该函数名作为URL的一部分放在地址栏中,就可以通过URL记录下当前页面的执行函数,这样在浏览器前进、后退或刷新等操作时,先获得当前URL找到相应的执行函数,然后重新执行该函数,即可获得正确的页面结果。

对每一个改变页面显示的JavaScript函数,需要在执行其业务逻辑之前,更改当前页面的URL,即将函数名及参数作为URL的Hash部分。例:

函数showPageInfo以页面显示条目数及页码为参数显示某一页的内容。则在其业务逻辑之前,需要修改页面URL。

       function showPageInfo( page_size , page_num ){

              //参数检查等

              ………

              // function_info是一个字符串,由函数名及相应参数组成的字符串

              var function_info = “showPageInfo(page_size , page_num )”;

              changeURLLocation(function_info);

             

              //业务逻辑

              ……..

       }

而函数changeURLLocation修改页面URL,将函数信息作为URL的Hash部分。

       function changeURLLocation( function_info ){

              // function_info是一个字符串,由函数名及相应参数组成的字符串

              //将函数信息作为新URL的Hash部分

              Var current_url = “http://somesite/#” + function_info;

              //将新URL写入地址栏

              window.location = current_url;

             

              ………

       }

同时,需要函数LocationChange(),当地址栏URL发生变化时,获得当前URL中的函数名及参数,并通过eval方法执行之。

       function LocationChange(){

              //第一步,获得当前页面URL中的函数名

              //注意,请不要使用window.location.hash,因为在笔者的使用过程中发现此种方法

              //可能出现错误

              var currentLocation = window.location.href;

              var function_info = “”;

          if( currentLocation && currentLocation.indexOf("#") > -1){

                 var index = currentLocation.indexOf("#");

                 if (currentLocation.length > (index+1)){

                        function_info = currentLocation.substring(index+1);

                 }

          }

             

              //第二步,重执行函数

              if (function_info == “” ){

                     //为空时默认执行某函数或做其它处理

                     ……

              } else{

                     //执行函数

                     try{

                            eval(function_info);

                     } catch(error){

                            ……

                     }

              }

       }

这样,当浏览器前进、后退或者刷新操作触发时,LocationChange()函数将能够获得当前页面的执行函数并执行之,也就能获得正确的页面响应了。但为了区分不同的页面,几乎每个页面操作都需要在URL上有所体现,即需要修改对应函数的某些参数,这就增加了程序的复杂度。

URL映射法

URL映射法的提出是基于对AJAX本质的这样一种认识:AJAX请求的本质是请求服务器资源的URL,以及执行AJAX响应的回调函数(如果是POST方法,还应包括POST的内容;如果是同步请求,还应包含同步请求的标志,这里一般认为是异步请求)。因此,只要记录下AJAX请求的URL及其回调函数,就可以重新执行该AJAX请求。

对不同页面,以地址栏URL为标识,记录下其对应的各个AJAX请求URL和回调函数。在浏览器前进、后退或刷新等操作时,先通过当前地址栏URL获得对应的各个AJAX请求URL和回调函数,然后重新发出这些AJAX请求,即可获得正确的页面结果。

函数sendAJAXRequest通过请求URL及回调函数callback发出AJAX异步请求。

      

       function sendAJAXRequest( request_url , callback ){

              //通过request_url发出AJAX异步请求,并通过callback执行响应

              ……

       }

对象historyStorage以键值对的形式存储每个地址栏URL对应的各个AJAX请求信息。一般来说,地址栏URL为键,而由于其对应AJAX请求可能多于一个,故值为包含各个AJAX请求信息二维数组。

       window.historyStorage = new Object();

      

如某页面地址栏URL为http://somesite/#showPageInfo(10,0),对应的AJAX异步请求的URL为request_url,回调函数为showPageInfo_Callback()。则存储在historyStorage中的形式为:

historyStorage[‘http://somesite/#showPageInfo(10,0)’] = [[request_url, showPageInfo_Callback]];

这样,函数showPageInfo()的实现应改为:

       function showPageInfo( page_size , page_num ){

              //参数检查等

              ………

              // current_url是地址栏URL,同时也是historyStorage的键

              var current_url = “http://somesite/#showPageInfo (page_size , page_num )”;

             

              //AJAX请求的URL

              var request_url = “SomeResource”;

              //AJAX请求的回调函数,处理异步响应

              var showPageInfo_Callback = function( response ){

                     //回调函数逻辑

                     ……

              }

              ……..

             

              // ajax_info_array用于存放各个AJAX请求信息

              var ajax_info_array = new Array();

              ajax_info_array[0] = [request_url , showPageInfo_Callback];

              saveHistory(current_url, ajax_info_array);

             

              //业务逻辑

              ……

       }

      

其中,函数saveHistory()将地址栏URL及其对应的各个AJAX请求信息存储在historyStorage中:

       function saveHistory( url , ajax_info_array ){

              //参数检查

              ……

              //存储在historyStorage中

              historyStorage[url] = ajax_info_array;

              ……

       }

与其对应的,函数getHistory()通过当前地址栏URL得到包含各个对应AJAX请求信息的二维数组:

       function getHistory( url ){

              //如果historyStorage中没有,返回空

              if ( typeof historyStorage[url] == “undefined” ){

                     return null;

              }

              //返回当前URL对应的各个AJAX请求,二维数组

              return historyStorage[url];

       }

同样,需要函数LocationChange(),但此时函数实现改为:

       function LocationChange(){

              //第一步,获得当前页面URL中的函数名

              var currentLocation = window.location.href;

             

              //第二步,得到对应的各个AJAX请求信息

              var ajax_info_array = getHistory(currentLocation);

              if (ajax_info_array == null ){

                     return;

              }

             

              //第三步,重发各个AJAX请求

              for (var i = 0 ; i < ajax_info_array.length ; i++){

                     //遍历每个对应的AJAX请求信息,重新发出各个AJAX请求

                     sendAJAXRequest( ajax_info_array[i][0] , ajax_info_array[i][1] );

              }

       }

这样,当浏览器前进、后退或者刷新操作触发时,LocationChange()函数先获得当前页面的URL,然后从historyStorage中找到对应的各个AJAX信息并依次重新发出,就能获得正确的页面响应。

这种方法不需要地址栏中给出函数名,但各种信息存贮在内存中,是一个占用。

      

以上两种方法,都暂时地解决了AJAX历史记录问题,但各有利弊,应据需要应变。当然,解决问题的方法多种多样,欢迎探讨。笔者相信,随着AJAX的发展,各种新问题、新办法都将出现,但只要抓住问题的本质都能够顺利解决。

查看所有评论(0)条】

最近评论



正在载入评论列表...
热点评论