XMLHttpRequest简介

要真正实现这种绚丽的奇迹,必须很是熟悉一个 JavaScript 对象,即 XMLHttpRequest。javascript

下面给出将要用于该对象的不多的几个 方法和属性。php

·open():创建到服务器的新请求。 
·send():向服务器发送请求。 
·abort():退出当前请求。 
·readyState:提供当前 HTML 的就绪状态。 
·responseText:服务器返回的请求响应文本。 java

1. 建立新的 XMLHttpRequest 对象程序员

<script language="javascript" type="text/javascript">
var request = new XMLHttpRequest();
</script>正则表达式

在 JavaScript 中用 var 建立一个变量,给它一个名字(如 “request”),而后赋给它一个新的 XMLHttpRequest 实例。此后就能够在函数中使用该对象了。编程

错误处理数组

在实际上各类事情均可能出错,而上面的代码没有提供任何错误处理。较好的办法是建立该对象,并在出现问题时优雅地退出。浏览器

2.建立具备错误处理能力的 XMLHttpRequest安全

<script language="javascript" type="text/javascript">
var request = false;
try {
  request = new XMLHttpRequest();
} catch (failed) {
  request = false;
}

if (!request)
  alert("Error initializing XMLHttpRequest!");
</script>

一、建立一个新变量 request 并赋值 false。后面将使用 false 做为断定条件,它表示尚未建立 XMLHttpRequest 对象。 
二、增长 try/catch 块: 
     1)尝试建立 XMLHttpRequest 对象。 
     2)若是失败(catch (failed))则保证 request 的值仍然为 false。 
三、检查 request 是否仍为 false(若是一切正常就不会是 false)。 
四、若是出现问题(request 是 false)则使用 JavaScript 警告通知用户出现了问题。 服务器

 增长对 Microsoft 浏览器IE6(如下)的支持

<script language="javascript" type="text/javascript">
var request = false;
try {
  request = new XMLHttpRequest();
} catch (trymicrosoft) {
  try {
    request = new ActiveXObject("Msxml2.XMLHTTP");
  } catch (othermicrosoft) {
    try {
      request = new ActiveXObject("Microsoft.XMLHTTP");
    } catch (failed) {
      request = false;
    }
  }
}

if (!request)
  alert("Error initializing XMLHttpRequest!");
</script>

一、建立一个新变量 request 并赋值 false。使用 false 做为判断条件,它表示尚未建立 XMLHttpRequest 对象。 
二、增长 try/catch 块: 
    1)尝试建立 XMLHttpRequest 对象。 
    2)若是失败(catch (trymicrosoft)): 
            1>尝试使用较新版本的 Microsoft 浏览器建立 Microsoft 兼容的对象(Msxml2.XMLHTTP)。 
            2> 若是失败(catch (othermicrosoft))尝试使用较老版本的 Microsoft 浏览器建立 Microsoft 兼容的对象(Microsoft.XMLHTTP)。 
    2)若是失败(catch (failed))则保证 request 的值仍然为 false。 
三、检查 request 是否仍然为 false(若是一切顺利就不会是 false)。 
四、若是出现问题(request 是 false)则使用 JavaScript 警告通知用户出现了问题。 

全部这些代码都直接嵌套在 script 标记中。像这种不放到方法或函数体中的 JavaScript 代码称为静态 JavaScript。就是说代码是在页面显示给用户以前的某个时候运行。(虽然根据规范不能彻底精确地 知道这些代码什么时候运行对浏览器有什么影响,可是能够保证这些代码在用户可以与页面交互以前运行。)这也是多数 Ajax 程序员建立 XMLHttpRequest 对象的通常方式。

将 XMLHttpRequest 建立代码移动到方法中

<script language="javascript" type="text/javascript">

var request;

function createRequest() {
  try {
    request = new XMLHttpRequest();
  } catch (trymicrosoft) {
    try {
      request = new ActiveXObject("Msxml2.XMLHTTP");
    } catch (othermicrosoft) {
      try {
        request = new ActiveXObject("Microsoft.XMLHTTP");
      } catch (failed) {
        request = false;
      }
    }
  }

  if (!request)
    alert("Error initializing XMLHttpRequest!");
}
</script>

 使用 XMLHttpRequest 的建立方法

<script language="javascript" type="text/javascript">

var request;

function createRequest() {
  try {
    request = new XMLHttpRequest();
  } catch (trymicrosoft) {
    try {
      request = new ActiveXObject("Msxml2.XMLHTTP");
    } catch (othermicrosoft) {
      try {
        request = new ActiveXObject("Microsoft.XMLHTTP");
      } catch (failed) {
        request = false;
      }
    }
  }

  if (!request)
    alert("Error initializing XMLHttpRequest!");
}

function getCustomerInfo() {
  createRequest();
  // Do something with the request variable
}
</script>

此代码唯一的问题是推迟了错误通知,这也是多数 Ajax 程序员不采用这一方法的缘由。假设一个复杂的表单有 10 或 15 个字段、选择框等,当用户在第 14 个字段(按照表单顺序从上到下)输入文本时要激活某些 Ajax 代码。这时候运行 getCustomerInfo() 尝试建立一个 XMLHttpRequest 对象,但(对于本例来讲)失败了。而后向用户显示一条警告,明确地告诉他们不能使用该应用程序。但用户已经花费了不少时间在表单中输入数据!这是很是使人讨厌的,而讨厌显然不会吸引用户再次访问您的网站。

用 XMLHttpRequest 发送请求

获得请求对象以后就能够进入请求/响应循环了。记住,XMLHttpRequest 唯一的目的是让您发送请求和接收响应。其余一切都是 JavaScript、CSS 或页面中其余代码的工做:改变用户界面、切换图像、解释服务器返回的数据。准备好 XMLHttpRequest 以后,就能够向服务器发送请求了。

Ajax 采用一种沙箱安全模型。所以,Ajax 代码(具体来讲就是 XMLHttpRequest 对象)只能对所在的同一个域发送请求。

设置服务器 URL

创建请求 URL

<script language="javascript" type="text/javascript">
   var request = false;
   try {
     request = new XMLHttpRequest();
   } catch (trymicrosoft) {
     try {
       request = new ActiveXObject("Msxml2.XMLHTTP");
     } catch (othermicrosoft) {
       try {
         request = new ActiveXObject("Microsoft.XMLHTTP");
       } catch (failed) {
         request = false;
       }  
     }
   }

   if (!request)
     alert("Error initializing XMLHttpRequest!");

   function getCustomerInfo() {
     var phone = document.getElementById("phone").value;
     var url = "/cgi-local/lookupCustomer.php?phone=" + escape(phone);
   }
</script>

Break Neck Pizza 表单

<body>
  <p><img src="breakneck-logo_4c.gif" alt="Break Neck Pizza" /></p>
  <form action="POST">
   <p>Enter your phone number:
    <input type="text" size="14" name="phone" id="phone" 
           onChange="getCustomerInfo();" />
   </p>
   <p>Your order will be delivered to:</p>
   <div id="address"></div>
   <p>Type your order in here:</p>
   <p><textarea name="order" rows="6" cols="50" id="order"></textarea></p>
   <p><input type="submit" value="Order Pizza" id="submit" /></p>
  </form>
</body>

当用户输入电话号码或者改变电话号码时,将触发getCustomerInfo() 方法。该方法取得电话号码并构造存储在 url 变量中的 URL 字符串。记住,因为 Ajax 代码是沙箱型的,于是只能链接到同一个域,实际上 URL 中不须要域名。该例中的脚本名为 /cgi-local/lookupCustomer.php。最后,电话号码做为 GET 参数附加到该脚本中:"phone=" + escape(phone)。

若是之前没用见过 escape() 方法,它用于转义不能用明文正确发送的任何字符。好比,电话号码中的空格将被转换成字符 %20,从而可以在 URL 中传递这些字符。

能够根据须要添加任意多个参数。好比,若是须要增长另外一个参数,只须要将其附加到 URL 中并用 “与”(&)字符分开 [第一个参数用问号(?)和脚本名分开]。

打开请求

有了要链接的 URL 后就能够配置请求了。能够用 XMLHttpRequest 对象的 open() 方法来完成。该方法有五个参数:

request-type:发送请求的类型。典型的值是 GET 或 POST,但也能够发送 HEAD 请求。 
url:要链接的 URL。 
asynch:若是但愿使用异步链接则为 true,不然为 false。该参数是可选的,默认为 true。 
username:若是须要身份验证,则能够在此指定用户名。该可选参数没有默认值。

password:若是须要身份验证,则能够在此指定口令。该可选参数没有默认值。 

open() 是打开吗?
Internet 开发人员对 open() 方法到底作什么没有达成一致。但它实际上并非 打开一个请求。若是监控 XHTML/Ajax 页面及其链接脚本之间的网络和数据传递,当调用 open() 方法时将看不到任何通讯。

一般使用其中的前三个参数。事实上,即便须要异步链接,也应该指定第三个参数为 “true”。这是默认值,但坚持明确指定请求是异步的仍是同步的更容易理解。

 

function getCustomerInfo() {
     var phone = document.getElementById("phone").value;
     var url = "/cgi-local/lookupCustomer.php?phone=" + escape(phone);
     request.open("GET", url, true);
   }

一旦用 open() 配置好以后,就能够发送请求了。幸运的是,发送请求的方法的名称要比 open() 适当,它就是 send()。

send() 只有一个参数,就是要发送的内容。可是在考虑这个方法以前,回想一下前面已经经过 URL 自己发送过数据了:

var url = "/cgi-local/lookupCustomer.php?phone=" + escape(phone);
虽然可使用 send() 发送数据,但也能经过 URL 自己发送数据。事实上,GET 请求(在典型的 Ajax 应用中大约占 80%)中,用 URL 发送数据要容易得多。若是须要发送安全信息或 XML,可能要考虑使用 send() 发送内容

。若是不须要经过 send() 传递数据,则只要传递 null 做为该方法的参数便可。

   function getCustomerInfo() {
     var phone = document.getElementById("phone").value;
     var url = "/cgi-local/lookupCustomer.php?phone=" + escape(phone);
     request.open("GET", url, true);
     request.send(null);
   }

 XMLHttpRequest 的一个简单属性 onreadystatechange。

由于是异步请求,因此 JavaScript 方法(例子中的 getCustomerInfo())不会等待服务器。所以代码将继续执行,就是说,将退出该方法而把控制返回给表单。用户能够继续输入信息,应用程序不会等待服务器。

这就提出了一个有趣的问题:服务器完成了请求以后会发生什么?答案是什么也不发生,至少对如今的代码而言如此!显然这样不行,所以服务器在完成经过 XMLHttpRequest 发送给它的请求处理以后须要某种指示说明怎么作。

在 JavaScript 中引用函数:
JavaScript 是一种弱类型的语言,能够用变量引用任何东西。所以若是声明了一个函数 updatePage(),JavaScript 也将该函数名看做是一个变量。换句话说,可用变量名 updatePage 在代码中引用函数。

设置回调方法

   function getCustomerInfo() {
     var phone = document.getElementById("phone").value;
     var url = "/cgi-local/lookupCustomer.php?phone=" + escape(phone);
     request.open("GET", url, true);
     request.onreadystatechange = updatePage;
     request.send(null);
   }

须要特别注意的是该属性在代码中设置的位置 —— 它是在调用 send() 以前 设置的。发送请求以前必须设置该属性,这样服务器在回答完成请求以后才能查看该属性。如今剩下的就只有编写 updatePage() 方法了

处理服务器响应

用户高兴地使用 Web 表单(同时服务器在处理请求),而如今服务器完成了请求处理。服务器查看 onreadystatechange 属性肯定要调用的方法。除此之外,能够将您的应用程序看做其余应用程序同样,不管是否异步。换句话说,不必定要采起特殊的动做编写响应服务器的方法,只须要改变表单,让用户访问另外一个 URL 或者作响应服务器须要的任何事情。

如今咱们已经看到如何告诉服务器完成后应该作什么:将 XMLHttpRequest 对象的 onreadystatechange 属性设置为要运行的函数名。这样,当服务器处理完请求后就会自动调用该函数。也不须要担忧该函数的任何参数。咱们从一个简单的方法开始

 回调方法的代码

<script language="javascript" type="text/javascript">
   var request = false;
   try {
     request = new XMLHttpRequest();
   } catch (trymicrosoft) {
     try {
       request = new ActiveXObject("Msxml2.XMLHTTP");
     } catch (othermicrosoft) {
       try {
         request = new ActiveXObject("Microsoft.XMLHTTP");
       } catch (failed) {
         request = false;
       }  
     }
   }

   if (!request)
     alert("Error initializing XMLHttpRequest!");

   function getCustomerInfo() {
     var phone = document.getElementById("phone").value;
     var url = "/cgi-local/lookupCustomer.php?phone=" + escape(phone);
     request.open("GET", url, true);
     request.onreadystatechange = updatePage;
     request.send(null);
   }

   function updatePage() {
     alert("Server is done!");
   }
</script>

它仅仅发出一些简单的警告,告诉您服务器何时完成了任务。

根据浏览器的不一样,在表单中止弹出警告以前会看到两次、三次甚至四次警告。这是怎么回事呢?原来咱们尚未考虑 HTTP 就绪状态,这是请求/响应循环中的一个重要部分。

HTTP 就绪状态

服务器在完成请求以后会在 XMLHttpRequest 的 onreadystatechange 属性中查找要调用的方法。这是真的,但还不完整。事实上,每当 HTTP 就绪状态改变时它都会调用该方法。

在 Ajax 应用程序中须要了解五种就绪状态:

·0:请求没有发出(在调用 open() 以前)。 
·1:请求已经创建但尚未发出(调用 send() 以前)。 
·2:请求已经发出正在处理之中(这里一般能够从响应获得内容头部)。 
·3:请求已经处理,响应中一般有部分数据可用,可是服务器尚未完成响应。 
·4:响应已完成,能够访问服务器响应并使用它。 

对于 Ajax 编程,须要直接处理的唯一状态就是就绪状态 4,它表示服务器响应已经完成,能够安全地使用响应数据了。

 检查就绪状态

   function updatePage() {
     if (request.readyState == 4)
       alert("Server is done!");
   }

修改后就能够保证服务器的处理已经完成。

HTTP 状态码

还有一个问题 —— 若是服务器响应请求并完成了处理可是报告了一个错误怎么办?要知道,服务器端代码应该明白它是由 Ajax、JSP、普通 HTML 表单或其余类型的代码调用的,但只能使用传统的 Web 专用方法报告信息。而在 Web 世界中,HTTP 代码能够处理请求中可能发生的各类问题。

您确定遇到过输入了错误的 URL 请求而获得 404 错误码的情形,它表示该页面不存在。这仅仅是 HTTP 请求可以收到的众多错误码中的一种(完整的状态码列表请参阅 参考资料 中的连接)。表示所访问数据受到保护或者禁止访问的 403 和 401 也很常见。不管哪一种状况,这些错误码都是从完成的响应 获得的。换句话说,服务器履行了请求(即 HTTP 就绪状态是 4)可是没有返回客户机预期的数据。

所以除了就绪状态外,还须要检查 HTTP 状态。咱们指望的状态码是 200,它表示一切顺利。若是就绪状态是 4 并且状态码是 200,就能够处理服务器的数据了,并且这些数据应该就是要求的数据(而不是错误或者其余有问题的信息)。所以还要在回调方法中增长状态检查

检查 HTTP 状态码

   function updatePage() {
     if (request.readyState == 4)
       if (request.status == 200)
         alert("Server is done!");
   }

为了增长更健壮的错误处理并尽可能避免过于复杂,能够增长一两个状态码检查

   function updatePage() {
     if (request.readyState == 4)
       if (request.status == 200)
         alert("Server is done!");
       else if (request.status == 404)
         alert("Request URL does not exist");
       else
         alert("Error: status code is " + request.status);
   }

如今能够确保请求已经处理完成(经过就绪状态),服务器给出了正常的响应(经过状态码),最后咱们能够处理服务器返回的数据了。返回的数据保存在 XMLHttpRequest 对象的 responseText 属性中。

   function updatePage() {
     if (request.readyState == 4) {
       if (request.status == 200) {
         var response = request.responseText.split("|");
         document.getElementById("order").value = response[0];
         document.getElementById("address").innerHTML =
           response[1].replace(/\n/g, "");
       } else
         alert("status is " + request.status);
     }
   }

获得 responseText 并使用 JavaScript split() 方法从管道符分开。获得的数组放到 response 中。

获得的数组放到 response 中。数组中的第一个值 —— 上一个订单 —— 用 response[0] 访问,被设置为 ID 为 “order” 的字段的值。第二个值 response[1],即客户地址,则须要更多一点处理。由于地址中的行用通常的行分隔符(“\n”字符)分隔,代码中须要用 XHTML 风格的行分隔符 <br /> 来代替。替换过程使用 replace() 函数和正则表达式完成。最后,修改后的文本做为 HTML 表单 div 中的内部 HTML。结果就是表单忽然用客户信息更新了

 XMLHttpRequest 的另外一个重要属性 responseXML。若是服务器选择使用 XML 响应则该属性包含(也许您已经猜到)XML 响应。处理 XML 响应和处理普通文本有很大不一样,涉及到解析、文档对象模型(DOM)和其余一些问题。

相关文章
相关标签/搜索