Ajax使用XML异步加载数据

在使用应用的时候,特别是独占式的应用,用户会持续地和应用进行交互,所以基于 Web的开发,网络延迟是一个很重要的因素,传统的web应用依赖于整个页面的重新加载。每一次发到服务器的调用都会打断用户的使用。这便需要异步加载数据来实现。

最早提供这种后台通信能力是使用 IFrame ,后来,XMLHttpRequest对象提供了更清晰和强大的功能。我们先来看一下这2个技术。

IFrame : I 字母代表的是“inline”,意味着它是另外一个文档布局的一部分。一个IFrame表现为DOM的一个元素,只要页面可见,我们就可以改变它的大小、移动、或者将它完全隐藏。关键是,我们使得了IFrame不可见,从表面来看,在不可见的元素里加载一些我们即将用到的数据,这并不影响用户当前的工作,这使得以后台方式获得数据成了可能。从此我们有了一种与服务器进行异步通讯的机制。虽然这只不过是一种  Hack 式的临时解决方案。

和其他的DOM元素一样,IFrame可以在HTML中声明,也可以使用 document.createElement()方法来创建。自然也可以通过getElementById()来获取它的引用。

 

< html xmlns = " http://www.w3.org/1999/xhtml "   >
< head runat = " server " >
    
< title > 无标题页 </ title >
    
< script type = " text/javascript " >
     window.onload
= function ()
     
{
        
var iframe=document.getElementById("dataFeed");
        
var src="datafeeds/mydata.xml";
        loadDataAsynchronously(iframe,src);
     }

     
function  loadDataAsynchronously(ifrmae,src)
     
{
        
//...............以后再说这里的功能。
     }
     
    
    
</ script >
</ head >
< body >
    
< form id = " form1 "  runat = " server " >
    
< div >
    
    
< iframe id = " dataFeed "  style = " width:0px; height:0px; " ></ iframe >
    
    
</ div >
    
</ form >
</ body >
</ html >



上面我们是通过前台的声明来创建了 IFrame ,当然也可以:

 

  function  fetchData()
{
      
var iframe=document.createElement("iframe");
      iframe.className
="hiddenDataFeed";
      document.body.appendChild(iframe);  
      
var src=''datafeeds/mydata.xml";
      loadDataAsynchronously(iframe,src);
}



设想、如果我们遵循创建IFrame来异步加载数据的话,随着应用的运行,将会创建出大量的IFrame,我们必须在用完的时候销毁它们,或者,就要实现一个类似于对象池(pooling)的机制。我们将在以后介绍到的设计模式中讲解关于对象池、队列以及其他用来保证大型应用流畅运转的机制。下面我们先来看一下关于异步加载的另一个可行的方案:

 

XMLDocument和XMLHttpRequest对象: 

XmLDocument和XMLHttpRequest并不是DOM的标准扩展,只是碰巧得到了多数浏览器的支持,它们的设计目的很明确,就是用来以后台方式获得数据。两者都是源自微软私有的ActiveX组件,可以在浏览器中作为JavaScript对象来访问。两者对象执行的功能很相似,只是 XMLHttpRequest对象可以更加精细地对请求进行控制,我们主要使用XMLHttpRequest。这里先来介绍一下 XMLDocument。

 

< script type = " text/javascript " >
    
function  getXMLDocument()     // 用来创建XMLDocument对象
     {
        
var xDoc=null;
        
if(document.implementation && document.implementation.createDocument)
        
{
            xDoc
=document.implementation.createDocument("","",null);//首先检查文档是否支持创建一个原生的XMLDocument对象所需的implementation属性。
                                                                    //implementation中文意思是“执行”,名词。如果支持则创建。
        }

        
else   //如果没有找到implementation属性,则测试浏览器是否支持ActiveX对象。
        {
            
if(typeof ActiveXObject != "undefined")
            
{
                
var msXmlAx=null;
                
try
                
{
                    msXmlAx
=new ActiveXObject("Msxml2.DOMDocument"); //如果支持ActiveX ,则先尝试第二版MSXML库来创建该对象。
                }

                
catch(e)
                
{
                    msXmlAx
=new ActiveXObject("Msxml.DOMDocument");//如果不支持新版MSXML库,则使用旧版创建该对象。
                }

                xDoc
=msXmlAx;
            }

        }

        
if(xDoc==null || typeof xDoc.load=="undefined")
        
{
            xDoc
=null;//如果上面两种方式都不支持,则简单地返回空的XMLDocument对象。我们将在后面详细讲解怎么才能更加优雅地处理这种情况。            
        }
 
        
return xDoc;
    }

    
</ script >

 

在上述函数getXMLDocument()中,我们并没有试图去猜测浏览器的版本,而是直接检测特定的对象是否可用,这种方法也称作对象检测(object detection)

下面我们来看 XMLHttpRequest对象:

同样,首先来创建XMLHttpRequest对象,使用对象检测,检测是否支持原生的XMLHttpRequest对象,如果不支持,则检测是否支持 ActiveX 对象,如果两个都不支持,则简单地返回null;

 

< html xmlns = " http://www.w3.org/1999/xhtml "   >
< head runat = " server " >
    
< title > 无标题页 </ title >
    
< script type = " text/javascript " >
    
function  getXMLHttpRequest()
    
{
        
var xRequest=null;
        
if(window.XMLHttpRequest)
        
{
            xRequest
=new XMLHttpRequest();
        }

        
else if(typeof ActiveXObject != "undefined")
             
{
                xRequest
=new ActiveXObject("Microsoft.XMLHTTP");            
             }

        
return xRequest;
    }

    
    
</ script >
</ head >
< body >
    
< form id = " form1 "  runat = " server " >
    
< div >
    
    
</ div >
    
</ form >
</ body >
</ html >

 

由上述代码,如果浏览器支持其中的一种,则我们就成功的创建了XMLHttpRequest对象。既然创建了对象,我们就要利用它,现在我们使用已经创建的XMLHttpRequest对象来向服务器发送数据。

通过XMLHttpRequest向服务器发送数据是一件很直接的事情,我们所要做的所有事情就是给它传递一个服务器页面的URL,这个页面将生成数据,如下:

 

< html xmlns = " http://www.w3.org/1999/xhtml "   >
< head runat = " server " >
    
< title > 无标题页 </ title >
    
< script type = " text/javascript " >
    
function  getXMLHttpRequest()
    
{
        
var xRequest=null;
        
if(window.XMLHttpRequest)
        
{
            xRequest
=new XMLHttpRequest();
        }

        
else if(typeof ActiveXObject != "undefined")
             
{
                xRequest
=new ActiveXObject("Microsoft.XMLHTTP");            
             }

        
return xRequest;
    }

    
    
function  sendRequest(url,params,HttpMethod)
    
{
        
if(!HttpMethod)
        
{
            HttpMethod
="POST";
        }

        
var req=getXMLHttpRequest();
        
if(req)
        
{
            req.open(HttpMethod,url,
true);
            req.setRequestHeader(
"Content-Type","application/x-www-form-urlencoded");
            req.send(params);
        }

    }
    
    
</ script >
</ head >
< body >
    
< form id = " form1 "  runat = " server " >
    
< div >
    
    
</ div >
    
</ form >
</ body >
</ html >

 

通过上面代码,我们成功地向服务器发送了一个请求,一个HTTP请求主要由 首部信息 和可能包含一些数据或参数的主体部分组成。响应则通常包括返回页面的HTML标记。这里我们将HTTP方法设置为POST请求方法。

简单说一下,HTTP方法有 "GET"用来获取文档;"POST"用来提交HTML表单;除外W3C还规约了一些其他的通用方法, "HEAD"用来获取一个文件的首部信息;"PUT"用来向服务器上传文档;"DELETE"用来删除服务器上的文档。

sendRequest()方法中包含的第二个和第三个参数都是可选参数,大部分情况都用不上。默认使用POST方法来获取资源,在请求的主体部分不需要传递任何参数。起上述代码对请求进行设置后,会立即将控制权返还给我我们,与此同时网络和服务器则正忙着他们自己的任务。这对于提高响应能力很有好处,但是我们怎样才能知道请求完成了呢?下面我们来讲解下。

使用回调函数监视请求:

处理异步通信的第二部分是在代码中设置一个入口,以便在调用结束的时候,可以获取结果,这通常是通过分配一个回调函数来实现的。也就是说,在未来某个不确定的时刻,当结果返回的时候,将会执行这一段代码。象我们平时见到的,window.onload函数以及UI控件上的onkeypress、onmouseover等都是回调函数。

下面我们来看下一个简单的回调处理函数的代码:

 

< html xmlns = " http://www.w3.org/1999/xhtml "   >
< head runat = " server " >
    
< title > 无标题页 </ title >
    
< script type = " text/javascript " >
    
var  READY_STATE_UNINITIALIZED = 0 ;    // 未初始化状态
     var  READY_STATE_LOADING = 1 ;              // 正在载如状态
     var  READY_STATE_LOADED = 2 ;               // 已载入状态标志
     var  READY_STATE_INTERACTIVE = 3 ;      // 交互状态
     var  READY_STATE_COMPLETE = 4 ;          // 完成
     var  req;
    
function  getXMLHttpRequest()
    
{
        
var xRequest=null;
        
if(window.XMLHttpRequest)
        
{
            xRequest
=new XMLHttpRequest();
        }

        
else if(typeof ActiveXObject != "undefined")
             
{
                xRequest
=new ActiveXObject("Microsoft.XMLHTTP");            
             }

        
return xRequest;
    }

    
    
function  sendRequest(url,params,HttpMethod)
    
{
        
if(!HttpMethod)
        
{
            HttpMethod
="POST";      //设置数据发送模式为POST
        }

        req
=getXMLHttpRequest();  //创建XMLHttpRequest实例
        if(req)
        
{
            req.onreadystatechange
=onReadyStateChange;   //当载入的状态变化,交给onReadyStateChange来处理
            req.open(HttpMethod,url,true);
            req.setRequestHeader(
"Content-Type","application/x-www-form-urlencoded");
            req.send(params);
        }

    }

    
function  onReadyStateChange()
    
{
        
var ready=req.readyState;  //获取XMLHttpRequest对象实例当前的状态
        var data=null;
        
if(ready==READY_STATE_COMPLETE)
        
{
            data
=req.responseText;   //如果请求发送已经完成,则将请求的数据内容保存在data变量中
        }

        
else
        
{
            data
="Loading...+["+ready+"]";  //如果请求发送尚未完成,则显示当前所处的状态
        }

        
//.....do sth. with the data
    }
    
    
</ script >
</ head >
< body >
    
< form id = " form1 "  runat = " server " >
    
< div >
    
    
</ div >
    
</ form >
</ body >
</ html >

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值