Javascript 基础---Ajax入门必看

Ajax 是现代Web 应用程序开发的一项关键工具。它让你能向服务器异步发送和接收数据,然后用 Javascript 解析。 Ajax 是 Asynchronous JavaScript and XML (异步JavaScript 与XML)的缩写。

Ajax 核心规范的名称继承于用来建立和发起请求的 Javascript 对象:XMLHttpRequest 。这个规范有两个等级。所有主流浏览器都实现了第一级,它代表了基础级别的功能。第二级扩展了最初的规范,纳入了额外的事件和一些功能来让它更容易与 form 元素协作,并且支持一些相关规范。

1. Ajax起步

Ajax 的关键在于 XMLHttpRequest 对象,而理解这个对象的方法是看个例子。下面代码展示了 XMLHttpRequest 对象的简单用法:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Example</title>
</head>
<body>
<div>
  <button>apples</button>
  <button>cherries</button>
  <button>bananas</button>
</div>
<div id="target">
  Press a button
</div>

<script type="application/javascript">
 var buttons = document.getElementsByTagName("button");
  for(var i=0; i<buttons.length; i++){
    buttons[i].onclick = handleButtonPress;
  }

  //脚本会调用此函数以响应 button 控件的 click 事件
  function handleButtonPress(e){
    //创建一个新的 XMLHttpRequest 对象
    var httpRequest = new XMLHttpRequest();
    //给 onreadystatechange 事件设置一个事件处理器
    httpRequest.onreadystatechange = handleResponse;
    //使用 open 方法来指定 HTTP 方法和需要请求的 URL (即告诉 httpRequest 对象你想要做的事)
    httpRequest.open("GET", e.target.innerHTML+".html");
    //这里没有向服务器发送任何数据,所以 send 方法无参数可用
    httpRequest.send();
  }

  //处理响应
  //一旦脚本调用了 send 方法,浏览器就会在后台发送请求到服务器。因为请求是在后台处理的,所以Ajax 依靠事件来通知这个请求的进展情况。
  function handleResponse(e){
    //当 onreadystatechange 事件被触发后,浏览器会把一个 Event 对象传递给指定的处理函数,target 属性则会被设为与此事件关联的XMLHttpRequest
    if(e.target.readyState == XMLHttpRequest.DONE && e.target.status == 200){ //请求成功
      document.getElementById("target").innerHTML = e.target.responseText; //显示被请求文档的内容
    }
  }
</script>
</body>
</html>

三个额外的文档非常简单:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Apples</title>
  <style>
    img { float:left;padding:2px;margin:5px;border: medium double black;background-color: lightgrey; width: 100px;height: 100px;}
  </style>
</head>
<body>
<p>
  <img src="../img/show-page/img_apples.jpg"/>
  Page for apples.
</p>
</body>
</html>

效果如下图所示:

随着用户点击各个水果按钮,浏览器会异步执行并取回所请求的文档,而主文档不会被重新加载。这就是典型的 Ajax 行为。

2. 使用 Ajax 事件

建立和探索一个简单的示例之后,可以开始深入了解 XMLHttpRequest 对象支持的功能,以及如何在请求中使用它们了。起点就是第二级规范里定义的那些额外事件:

这些事件大多数会在请求的某一特定时间点上触发。 readystatechange 和 progress 这两个事件是例外,它们可以多次触发以提供进度更新。

调度这些事件时,浏览器会对 readystatechange 事件使用常规的 Event 对象,对其他事件则使用 ProgressEvent 对象。 ProgressEvent 对象定义了 Event 对象的所有成员,并增加了下图中介绍的这些成员:

下面代码展示了如何使用这些事件:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Example</title>
  <style>
    table {margin: 10px;border-collapse: collapse; float: left;}
    div{margin: 10px;}
    td,th{padding: 4px;}
  </style>
</head>
<body>
<div>
  <button>apples</button>
  <button>cherries</button>
  <button>bananas</button>
</div>
<table id="events" border="1"></table>
<div id="target">
  Press a button
</div>

<script type="application/javascript">
  var buttons = document.getElementsByTagName("button");
  for(var i=0; i<buttons.length; i++){
    buttons[i].onclick = handleButtonPress;
  }

    var httpRequest;
  function handleButtonPress(e){
    clearEventDetails();
    httpRequest = new XMLHttpRequest();
    httpRequest.onreadystatechange = handleResponse;

    httpRequest.onerror = handleError;
    httpRequest.onload = handleLoad;;
    httpRequest.onloadend = handleLoadEnd;
    httpRequest.onloadstart = handleLoadStart;;
    httpRequest.onprogress = handleProgress;

    httpRequest.open("GET", e.target.innerHTML+".html");
    httpRequest.send();
  }

  function handleResponse(e){
    displayEventDetails("readystate("+httpRequest.readyState+")")
    if(e.target.readyState == XMLHttpRequest.DONE && e.target.status == 200){
      document.getElementById("target").innerHTML = e.target.responseText;
    }
  }

  function handleError(e){ displayEventDetails("error",e);}
  function handleLoad(e){ displayEventDetails("load",e);}
  function handleLoadEnd(e){ displayEventDetails("loadend",e);}
  function handleLoadStart(e){ displayEventDetails("loadstart",e);}
  function handleProgress(e){ displayEventDetails("progress",e);}

  function clearEventDetails(){
    document.getElementById("events").innerHTML = "<tr><th>Event</th><th>lengthComputable</th><th>loaded</th><th>total</th>";
  }

  function displayEventDetails(eventName,e){
    if(e){
      document.getElementById("events").innerHTML
          +="<tr><td>"+eventName+"</td><td>"+ e.lengthComputable+"</td><td>"+ e.loaded+"</td><td>"+ e.total+"</td></tr>";
    }else {
      document.getElementById("events").innerHTML += "<tr><td>"+eventName+"</td><td>NA</td><td>NA</td><td>NA</td></tr>";
    }
  }
</script>
</body>
</html>

这是之前示例的一种变型,为一些事件注册了处理函数,并在一个 table 元素里为处理的每个事件都创建了一条记录。从下图中可以看到 Firefox 浏览器是如何触发这些事件的。

3. 处理错误

使用 Ajax 时必须留心两类错误。它们之间的区别源于视角不同。

第一类错误是从 XMLHttpRequest 对象的角度看到的问题:某些因素阻止了请求发送到服务器。例如 DNS 无法解析主机名,连接请求被拒绝,或者URL无效。

第二类问题是从应用程序的角度看到的问题,而非 XMLHttpRequest 对象。它们发生于请求成功发送至服务器,服务器接收请求、进行处理并生成响应,但该响应并不指向你期望的内容。例如,如果请求的URL 不存在,这类问题就会发生。

有三种方式可以处理这些错误,如下面代码所示:

3.1 处理设置错误

需要处理的第一类问题是向 XMLHttpResquest 对象传递了错误的数据,比如格式不正确的 URL 。它们极其容易发生在生成基于用户输入的URL 时。为了模拟这类问题,上面文档中有添加一个标签 Bad URL (错误的URL)的button 。按下这个按钮会以以下形式调用 open 方法:

httpRequest.open("GET","http://")

这是一种会阻止请求执行的错误,而 XMLHttpRequest 对象会发生这类事件时抛出一个错误。这就意味着需要用一条 try...catch 语句来围住设置请求的代码,就像这样:

try{
      ...
      httpRequest.open("GET","http://")
      ...
      httpRequest.send();
    }catch(error){
      displayErrorMsg("try/catch",error.message)
    }

catch 子句让你有机会从错误中恢复。可以选择提示用户输入一个值,也可以回退至默认的URL ,或是简单地丢弃这个请求。 在这个例子中,仅仅调用了 displayErrorMsg 函数来显示错误消息。

3.2 处理请求错误

第二类错误发生在请求已生成,但其他方面出错时。为了模拟这类问题,在示例中添加了一个标签为 Bad Host (错误主机)的按钮。当这个按钮被按下后,就会调用 open 方法访问一个不可用的 URL:

httpRequest.open("GET",http://www.ycdoitt.com/nopage.html)

这个URL 存在两个问题。第一个问题是主机名不能被 DNS 解析,因此浏览器无法生成服务器连接。这个问题知道 XMLHttpRequest 对象开始生成请求时才会变得明显,因此它会以两种方式发出错误信号。如果你注册了一个 error 事件的监听器,浏览器就会向你的监听函数发送一个 Event 对象。以下是示例中使用的函数:

function handleError(e){
    displayErrorMsg("Error event",httpRequest.status + httpRequest.statusText);
  }

当这类错误发生时,能从 XMLHttpRequest 对象获得何种程度的信息取决于浏览器,遗憾的是大多数情况下,会得到的值为 0的 status和空白的 statusText 值。

第二个问题是URL和生成请求的具有不同的来源,在默认情况下这是不允许的。你通常只能向载入脚本的同源URL发送Ajax请求。浏览器报告这个问题时可能会抛出 Error 或者触发error事件,不同浏览器的处理方法不尽相同。不同浏览器还会在不同的时点检查来源,这就意味着不一定总是能看到浏览器对同一问题突出显示。可以使用跨站资源规范(CORS,Cross-Origin Resource Sharing)来绕过同源限制。

3.3 处理应用程序错误

最后一类错误发生于请求成功完成(从XMLHttpRequest对象的角度看),但没有返回你想要的数据时。为了制造这类问题,在上面示例中添加一个说明标签为 cucumber 的 button 。按下这个按钮会生成类似于 apples、cherries 和 bananas 按钮那样的请求URL,但是在服务器上不存在 cucumber.html 这个文档。

这一过程本身没有错误(因为请求已完成),需要根据 status属性来确定发生了什么。当请求某个存在的文档时,会获得404这个状态码,它的意思是服务器无法找到请求的文档。可以看到示例是如何处理200(意思是OK)以外的状态码的:

if(httpRequest.status == 200){
        target.innerHTML = httpRequest.responseText;
      }else{
        document.getElementById("statusmsg").innerHTML
            = "Status:" + httpRequest.status +" "+ httpRequest.statusText;
      }

在这个例子中,只是简单的显示了status和statusText的值。而在真正的应用程序里,需要以一种有用且有意义的方式进行恢复(比如显示备用内容或警告用户有问题,具体看哪种更适合应用程序)。

4. 获取和设置标头

使用XMLHttpRequest对象,可以设置发送给服务器的请求标头(Header)和读取服务器响应里的标头。

4.1 覆盖请求的HTTP方法

通常不需要添加或修改Ajax请求里的标头。浏览器知道需要发送些什么,服务器也知道如何进行响应。不过,有几种情况例外。第一种是 X-HTTP-Method-Override 标头。

HTTP标准通常被用于在互联网上请求和传输HTML文档,它定义了许多方法。大多数人都知道GET和POST,因为它们的使用最为广泛。不过还存在其他一些方法(包括PUT和DELETE),这些HTTP方法用来给向服务器请求的URL赋予意义,而且这种用法正在呈现上升趋势。举个例子,假如想查看某条用户记录,可以生成这样一个请求:

httpRequest.open("GET","http://myserver/records/freeman/adam");

这里只展示了HTTP方法和请求的URL。要使这个请求能顺利工作,服务器端必须由应用程序能理解这个请求,并将它转变成一段合适的数据以发送回服务器。如果想删除数据,可以这么写:

httpRequest.open("DELETE","http://myserver/records/freeman/adam");

此处的关键在于通过HTTP方法表达出你想让服务器做什么,而不是把它用某种方式编码进URL。

以这种方式使用HTTP方法的问题在于:许多主流的Web技术只支持GET和POST,而且不少防火墙只允许GET和POST请求通过。有一种惯用的做法可以规避这个限制,就是使用 X-HTTP-Method-Override标头来指定想要使用的HTTP方法,但形式上市在发送一个POST请求。代码演示如下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Example</title>
</head>
<body>
<div>
  <button>apples</button>
  <button>cherries</button>
  <button>bananas</button>
</div>
<div id="target">Press a button</div>

<script>
  var buttons = document.getElementsByTagName("button");
  for(var i = 0; i < buttons.length; i++){
    buttons[i].onclick = handleButtonPress;
  }

  var httpRequest;
  function handleButtonPress(e){
    httpRequest = new XMLHttpRequest();
    httpRequest.onreadystatechange = handleResponse;
    httpRequest.open("GET", e.target.innerHTML+".html");
    httpRequest.setRequestHeader("X-HTTP-Method-Override","DELETE");
    httpRequest.send();
  }

  function handleError(e){
    displayErrorMsg("Error event",httpRequest.status+httpRequest.statusText);
  }

  function handleResponse(){
    if(httpRequest.readyState == 4 && httpRequest.status == 200){
      document.getElementById("target").innerHTML = httpRequest.responseText;
    }
  }
</script>
</body>
</html>

在这个例子中,有使用XMLHttpRequest对象上的setRequestHeader方法来表明想让这个请求以HTTP DELETE方法的形式进行处理。请注意我在调用open方法之后才设置了这个标头。如果试图在open方法之前使用setRequestHeader方法,XMLHttpRequest对象就会抛出一个错误。

PS:覆盖HTTP需要服务器端的Web应用程序框架能理解X-HTTP-Method-Override这个惯例,并且你的服务器端应用程序要设置成能寻找和理解那些用的较少的HTTP方法。

4.2 禁用内容缓存

第二个可以添加到Ajax请求上的有用标头是Cache-Control,它在编写和调试脚本时尤其有用。一些浏览器会缓存通过Ajax请求所获得的内容,在浏览会话期间不会再请求它。对在前面的例子而言,意味着 apples.html、cherries.html和bananas.html 上的改动不会立即反映到浏览器中。下面代码展示了可以如何设置标头来避免这一点:

httpRequest = new XMLHttpRequest();
    httpRequest.onreadystatechange = handleResponse;
    httpRequest.open("GET", e.target.innerHTML+".html");
    httpRequest.setRequestHeader("Cache-Control","no-cache");
    httpRequest.send();

设置标头的方式和之前的例子一样,但这次用到的标头是 Cache-Control,而想要的值是 no-cache。放置这条语句后,如果通过Ajax请求的内容发生了改变,就会在下一次请求文档时体现出来。

4.3 读取响应标头

可以通过 getResponseHeader 和 getAllResponseHeaders 方法来读取服务器响应某个Ajax请求时发送的HTTP标头。在大多数情况下,你不需要关心标头里有什么,因为它们是浏览器和服务器之间交互事务的组成部分。下面代码展示了如何使用这个属性:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta content="width=device-width,user-scalable=no" name="viewport" />
  <meta name="author" content="叶超Luka" />
  <meta name="description" content="A simple example" />
  <title>Example</title>
  <link href="../img/ycdoit.ico" type="image/x-icon" rel="shortcut icon" />
  <style>
    #allheaders,#ctheader{border: medium solid black;padding: 2px;margin: 2px;}
  </style>
</head>
<body>
<div>
  <button>apples</button>
  <button>cherries</button>
  <button>bananas</button>
</div>
<div id="ctheader"></div>
<div id="allheaders"></div>
<div id="target">Press a button</div>

<script>
  var buttons = document.getElementsByTagName("button");
  for(var i = 0; i < buttons.length; i++){
    buttons[i].onclick = handleButtonPress;
  }

  var httpRequest;
  function handleButtonPress(e){
    httpRequest = new XMLHttpRequest();
    httpRequest.onreadystatechange = handleResponse;
    httpRequest.open("GET", e.target.innerHTML+".html");
    httpRequest.setRequestHeader("Cache-Control","no-cache");
    httpRequest.send();
  }

  function handleResponse(){
    if(httpRequest.readyState==2){
      document.getElementById("allheaders").innerHTML = httpRequest.getAllResponseHeaders();
      document.getElementById("ctheader").innerHTML = httpRequest.getResponseHeader("Content-Type");
    }else if(httpRequest.readyState == 4 && httpRequest.status == 200){
      document.getElementById("target").innerHTML = httpRequest.responseText;
    }
  }
</script>
</body>
</html>

效果图如下:

根据此图可以看出开发服务器正在运行的Web服务器软件是 IntelliJ IDEA 15.0.4,最后修改 apples.html 文档的时间是6月27日(但屏幕截图是7月5日)。

(0)

相关推荐

  • AJAX技术基础介绍

    基于XML的异步JavaScript,简称AJAX,是当前Web创新(称为Web2.0)中的一个王冠.感谢组成AJAX的各种技术,Web应用的交互如Flickr, Backpack和Google在这方面已经有质的飞跃.这个术语源自描述从基于网页的Web应用到基于数据的应用的转换.在基于数据的应用中,用户需求的数据如联系人列表,可以从独立于实际网页的服务端取得并且可以被动态地写入网页中,给缓慢的Web应用体验着色使之像桌面应用一样. 虽然大部分开发人员在过去使用过XMLHttp或者使用Iframe

  • JQuery的ajax基础上的超强GridView展示

    看到一个这样的例子和大家分享下.这个一直是我想要做到的. 首先先展示下最终的样子: 使用northwind的数据.点击前面的加号会把其它属于这个产品的详细订单展示出来,而每个产品后面都会有它的订单个数.点击'+'后的样子: 先分析下它的实现: 第一个图的显示是个Gridview,当点击每条记录前面的'+'时会使用jQuery的ajax功能调用一个Web Method,并传输一个当前产品的ID进去,然后会定义一个继承UserControl的类,它能够添加一个ascx文件,然后这个类里面定义一个Vi

  • Ajax.基础教程 电子书版 提供下载

    Ajax.基础教程提供下载时间为2个星期以内,需要的抓紧下 screen.width-461) window.open('/upload/200729131038873.jpg');" src="http://files.jb51.net/upload/200729131038873.jpg" border=0> http://www.javascript.com.cn/Ajax.pdf 最好用迅雷下 (此资源来源于网络,如果侵犯您的版权,我们会马上删掉)

  • Jquery ajax基础教程

    jQuery的Ajax带来了无需刷新的web页面革命.这里就详细介绍一下jQuery所涉及到的Ajax操作.(无需特殊说明,均需要有服务器配置,这里本人用的是Tomcat 7) 1.基于请求加载文件数据 这里的请求通常都是网页的某些操作,如点击等. 而其加载数据的类型归类为以下四种:a.加载HTML文件:b.加载JSON文件:c.加载Javascript文件:d.加载XML文件. 其对应的四种加载方法分别是:load.getJSON.getScript.get. a.加载HTML文件 把编写好的

  • ajax 入门基础之 XMLHttpRequest对象总结

    XMLHttpRequest 提供客户端同http服务器通讯的协议 一:创建 IE : http_request = new ActiveXObject("Msxml2.XMLHTTP"); http_request = new ActiveXObject("Microsoft.XMLHTTP"); 非IE: http_request = new XMLHttpRequest(); 二:onreadystatechange 指定当readyState属性改变时的事件

  • 使用jQuery处理AJAX请求的基础学习教程

    $.ajax快捷方法 $.get(url,[data],[callback],[type]) $.post(url,[data],[callback],[type]) 两种方法请求方式不同,其他方式相同. 参数:url[请求地址],data[请求的数据内容(obj对象)],callback[回调函数(只能处理请求成功事件)], type[请求返回数据的编码格式(默认ContentType指定格式)] $.get('/test?x=1'); $.get('/test',{z:2}); $.post

  • Ajax基础知识详解

    Ajax主要的功能是实现了浏览器端 异步 访问服务器:通过浏览器的XMLHttpRequest对象发出小部分数据,与服务端进行交互,服务端返回小部分数据,然后更新客户端的部分页面. 1.先实例化XMLHttpRequest对象 var request; if (window.XMLHttpRequest){ request=new XMLHttpRequest(); } else{ request=new ActiveXObject("Microsoft.XMLHTTP"); //兼容

  • ajax跨域(基础域名相同)表单提交的方法

    本文实例讲述了ajax跨域(基础域名相同)表单提交的方法.分享给大家供大家参考.具体如下: 1.要在做ajax提交的页面中添加如下js语句: <script type="text/javascript"> document.domain="基础域名"; </script> 2.ajax表单提交表单时可以使用一个jquery的一个表单插件jquery.form.js 使用语法如下: //fromPost为要收集数据的form表单的id $(&q

  • Ajax+PHP简单基础入门实例教程

    首先我们来了解怎么在javascript中创建这个对象: 程序代码 var xmlHttp = new XMLHttpRequest(); 这行简单的代码在 Mozilla.Firefox.Safari.Opera 以及基本上所有以任何形式或方式支持 Ajax 的非 Microsoft 浏览器中,创建了 XMLHttpRequest 对象.但是对于市场占有率达到70%的IE来说,这种方法是不行的,而不同的IE版本还有不同的创建方法,所以我们需要在IE下面使用下面两种创建对象的办法: 程序代码 t

  • 零基础学习AJAX之AJAX的简介和基础

    本节简介(异步链接服务器对象)XMLHTTPRequest以及AJAX的简介. AJAX即"Asynchronous Javascript And XML"(异步JavaScript和XML). AJAX有四个方面的好处:1.即减轻了服务器的负担.2带来了更好的用户体验.3.基于标准被广泛的支持.4.拥有更好的页面呈现和数据分离. 技术名称 技术说明 javascript javascript是通用的脚本语言,AJAX是用javascript编写的 css 用户界面的样式通过css来修

随机推荐