关于ajax的debug小记一则--小问题往往容易被忽略

今天写程序的时候遇到一个问题,费了不少功夫才把bug给找出来了。本来其实是很简单的问题,不过一开始的时候还是忽略了。看来低级错误还是一如既往的难以避免,特以此文记之,希望以后不会再犯同类的错误。

问题描述:

主页上定义用来显示数据的div,当页面触发了某个事件(如<select>的onchange()),就从database加载数据在该div内显示出来。而数据是用一个table来显示的,该table有css文件和javascript来设置style。

因为涉及到database的数据加载,我决定用ajax来做。于是,整个流程如下:

触发事件(select.onchange()) --> ajax (XMLHttpRequest) --> set table style(用css和javascript方法来实现)

为了方便代码的重用,把ajax那部分做成了单独的一个loadXMLDoc.js文件,并设定了一些传入参数,使得该部分代码更通用化,代码如下:

 

/*
This function is to load a file by sending xmlhttprequest
When the data is being transferred, show some information to the user (usually, the info would be a loading image)
When the file loaded, display the file in the specified div
@docUrl: the file to be laoded
@docDisDiv: the div to display the file
@infoHtml: the html string, eg: "<img src='image/22-1.gif' alt='loading...'></img>";
@infoDiv: the div to display the waiting info
*/
 
function  loadXMLDoc(docUrl,docDisDiv,infoHtml,infoDiv){
    
var  xmlhttp = null ;
    
if  (window.XMLHttpRequest){ //  code for Firefox, Opera, IE7, etc.
        xmlhttp = new  XMLHttpRequest();
    }
else   if  (window.ActiveXObject){ //  code for IE6, IE5
        xmlhttp = new  ActiveXObject( " Microsoft.XMLHTTP " );
    }
if  (xmlhttp != null ){
        xmlhttp.onreadystatechange 
=   function (){
            
if  (xmlhttp.readyState == 4 ){ //  4 = "loaded"
                 if  (xmlhttp.status == 200 ){ //  200 = "OK"
                    document.getElementById(docDisDiv).innerHTML = xmlhttp.responseText; // load data
                    document.getElementById(infoDiv).innerHTML  =   "" ; // data loaded, clear waiting info
                } else {
                    alert(
" Problem retrieving data: "   +  xmlhttp.statusText);
                }
            }
else {
                document.getElementById(infoDiv).innerHTML 
=  infoHtml; // waiting data transfering, display waiting info...
            }
        }
        xmlhttp.open(
" GET " ,docUrl, true );
        xmlhttp.send(
null );
    }
else {
        alert(
" Your browser does not support XMLHTTP. " );
    }
}

熟悉ajax的同志都应该清楚,这是对一个典型的“ajax文件加载请求”代码,只是里面做了作了小小的修改,传入了几个参数而已。

 

好了,下面再来看看op.php内的内容:

< div >
< table id = " listTable " >
< caption > The Latest Purchase Order </ caption >
    
< thead >
    
< tr  class = " odd " >
        
< th scope = " col "  abbr = " ORDER ID " > Order ID </ th >
        
< th scope = " col "  abbr = " SELLER ID " > Seller ID </ th >
        
< th scope = " col "  abbr = " EMPLOYEE ID " > Employee ID </ th >
        
< th scope = " col "  abbr = " DATE " > Date </ th >
        
< th scope = " col "  abbr = " STATUS " > Status </ th >
    
</ tr >     
    
</ thead >    
    
< tbody >
<? php
require_once ' lib/ListTableData.php ' ;
$table   =   " order_purchase " ;
$fields   =   array ( " order_id " , " seller_id " , " employee_id " , " date " , " status " );
$sql   =   " SELECT * FROM order_purchase ORDER BY date DESC LIMIT 20 " ;
$dataList   =   new  ListTableData( $table , $fields , $sql );
$dataList -> printData();
?>
</ tbody >
</ table >
</ div >

关于这个文件的代码,其实也不用理会,只要明白,这个table有个id属性,然后外部代码根据这个id就可以将这个table的style按照css和js定义好风格来设置。

 

最后,我们再来看看在index.php中代码是怎么被调用的:

var  docUrl  =   " op.php " ;    
var  docDiv  =   " right_top_itemlist " ;
var  infoHtml  =   " <img src='image/22-1.gif' alt='loading...'></img> " ;
var  infoDiv  =   " loading_info_div " ;

loadXMLDoc(docUrl,docDiv,infoHtml,infoDiv);//load file and construct table
setTableStyle(“listTable”);//set the style of the table

loadXMLDoc(docUrl,docDiv,infoHtml,infoDiv);    这一行就没什么说的了,就是调用那个js文件的方法。

setTableStyle();    这一行目的就是将加载后的table的style设置好,至于当中的style代码跟这个主题无关紧要,因此不用理会,知道它的作用就行了。

简单概括一下就是:发送ajax请求,文件加载的时候显示等候信息,当文件加载完就以table的形式显示数据,然后将table的style设置好。

好了,开始测试。测试结果:在IE下,成功得到了设想当中的效果,可是在Firefox下,只能成功加载数据,但表格的style设置不成功。

于是用firefox的debug工具,在其中一个js语句内:

var  Ptr = document.getElementById(id).getElementsByTagName( ' tr ' );

出现了如下的错误信息:error document.getElementById(id) has no properties(其中的id就是我从外面传进去的一个table的名字,在这里也就是“listTable”了) 。

我一直都很纳闷,不知道为什么会出现这个error,因为我通过alert()方法测试,确定“listTable”已经正确传进去了,但是为什么却又出现了这个错误呢?代码改来改去,不断的测试,可还是百思不得其解。。。

后来,我在设置table的那段代码中加入了一个语句来测试所有"tr”标签的总数量,结果发现,每次alert出来的<tr>标签的数量竟然不是当前加载的table的<tr>的数量,而是上一次加载的table的那个数量,也就是说,这段"setTableStyle" 代码set的根本就不是当前显示数据的那个table,而是上一次加载数据的那个table。(在这里要补充一下:由于加载的那些数据是动态的,因此每次加载的行数,也就是<tr>的数量都不同的)那它的style是当然不可能被正确设置了。可是,为什么会出现这样的问题呢?明明就是在loadXMLDoc()之后setTableStyle()了啊。。。并且,在IE下面也是成功通过的啊。。。到底是哪里出的问题呢?想啊想,debug啊debug。。。几乎抓破头皮了,还是没找出来原因。。。

后来,突然脑海好像闪了一下的样子。。。我想到了些东西。。。

对!问题就在这里,一定是这里:
        xmlhttp.onreadystatechange  =   function (){
            
if  (xmlhttp.readyState == 4 ){ //  4 = "loaded"
                 if  (xmlhttp.status == 200 ){ //  200 = "OK"
                     ...

当xmlhttp请求发送出去以后,先从database提取数据,然后数据返回来,然后才去构造那个"listTable”,而并不是马上就将"listTable”构建的,是需要一定时间的,这也是为什么我们很多时候将loading image显示出来的原因!显然,当loadXMLDoc()被执行之后,紧跟着就执行setTableStyle(),从表面上看执行顺序是没错的,然而实际上是,当setTableStyle()开始运行时,xmlhttp还在请求当中,数据还没完全返回来,"listTable” 根本还没有构建起来。。。这也就是为什么,后来我alert()得到的<tr>数目并不是当前显示的table的tr数目,而是上一个table的tr数目--因为这时候,新的table根本还没构建。。。也就是说,当新的table构建好以后,根本就没有对当前的table进行setTableStyle(),而是对上个table做了。

后来将setTableStyle()的调用放在了xmlhttp的请求完成后,也就是:

xmlhttp.onreadystatechange  =   function (){
     
if  (xmlhttp.readyState == 4 ){ //  4 = "loaded"
             if  (xmlhttp.status == 200 ){ //  200 = "OK"
                   document.getElementById(docDisDiv).innerHTML = xmlhttp.responseText; // load data
                   document.getElementById(infoDiv).innerHTML  =   "" ; // data loaded, clear waiting info
                   setTableStyle();
                }
else {
                    alert(
" Problem retrieving data: "   +  xmlhttp.statusText);
                }

终于,成功了。再debug就没有错了,无论是在ie下还是ff下。。。

其实说了一大堆也就是一言可以蔽之:在使用ajax xmlhttprequest的时候要注意,方法的调用时机要合适,不能想当然。

正如我在文章开头说到的,本来是一个很基本的问题,但是因为没有注意好,结果弄了大半天才高明白,bs一下自己。。。

不过,这里又提出了一个问题,不知道为什么,在ie下面,没有出现这个问题的呢???这个问题所反映出的ie和ff两个浏览器的机制的不同点究竟是什么?值得探讨。。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值