• Ajax学习笔记— XMLHttpRequest


    简单的new

    首先需要创建一个新变量并赋给它一个 XMLHttpRequest 对象实例。这在 JavaScript 中很简单,只要对该对象名使用 new 关键字即可,如 清单 1 所示。

    清单 1. 创建新的 XMLHttpRequest 对象

    <script language="javascript" type="text/javascript">
    var request = new XMLHttpRequest();
    </script>

    记住,JavaScript 不要求指定变量类型,因此不需要像 清单 2 那样做(在 Java 语言中可能需要这样)。

    清单2.创建XMLHttpRequest的Java伪代码

    XMLHttpRequest request = new XMLHttpRequest();

    清单 3. 创建具有错误处理能力的 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>

         具体添加对浏览器的支持,查看参考链接。

         像这种不放到方法或函数体中的 JavaScript 代码称为静态 JavaScript。就是说代码是在页面显示给用户之前的某个时候运行。(虽然根据规范不能完全精确地 知道这些代码何时运行对浏览器有什么影响,但是可以保证这些代码在用户能够与页面交互之前运行。)这也是多数 Ajax 程序员创建 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 发送请求

           清单 7. 建立请求 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>

         清单 8. Break Neck Pizza 表单(与表单7的代码匹配)

    <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>

         打开请求:

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

    • request-type:发送请求的类型。典型的值是 GET 或 POST,但也可以发送 HEAD 请求。
    • url:要连接的 URL。
    • asynch:如果希望使用异步连接则为 true,否则为 false。该参数是可选的,默认为 true。
    • username:如果需要身份验证,则可以在此指定用户名。该可选参数没有默认值。
    • password:如果需要身份验证,则可以在此指定口令。该可选参数没有默认值。

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

    将这些结合起来,通常会得到 清单 9 所示的一行代码。

         清单 9. 打开请求

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

         一旦设置好了 URL,其他就简单了。多数请求使用 GET 就够了(后面的文章中将看到需要使用 POST 的情况),再加上 URL,这就是使用 open() 方法需要的全部内容了。

    发送请求:

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

    var url = "/cgi-local/lookupCustomer.php?phone=" + escape(phone);

         虽然可以使用 send() 发送数据,但也能通过 URL 本身发送数据。事实上,GET 请求(在典型的 Ajax 应用中大约占 80%)中,用 URL 发送数据要容易得多。如果需要发送安全信息或 XML,可能要考虑使用 send() 发送内容(本系列的后续文章中将讨论安全数据和 XML 消息)。如果不需要通过 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);
       }

    指定回调方法:

    回调方法就是服务器完成响应后,触发浏览器执行的方法。

    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() 之前 设置的。发送请求之前必须设置该属性,这样服务器在回答完成请求之后才能查看该属性。


    回调方法:

    在看该方法的细节前先了解两个东西:

    HTTP 就绪状态:

         服务器在完成请求之后会在 XMLHttpRequest 的 onreadystatechange 属性中查找要调用的方法。这是真的,但还不完整。事实上,每当 HTTP 就绪状态改变时它都会调用该方法。这意味着什么呢?首先必须理解 HTTP 就绪状态。

          HTTP 就绪状态表示请求的状态或情形。它用于确定该请求是否已经开始、是否得到了响应或者请求/响应模型是否已经完成。它还可以帮助确定读取服务器提供的响应文本或数据是否安全。在 Ajax 应用程序中需要了解五种就绪状态:

    • 0:请求没有发出(在调用 open() 之前)。
    • 1:请求已经建立但还没有发出(调用 send() 之前)。
    • 2:请求已经发出正在处理之中(这里通常可以从响应得到内容头部)。
    • 3:请求已经处理,响应中通常有部分数据可用,但是服务器还没有完成响应。
    • 4:响应已完成,可以访问服务器响应并使用它。

           与大多数跨浏览器问题一样,这些就绪状态的使用也不尽一致。您也许期望任务就绪状态从 0 到 1、2、3 再到 4,但实际上很少是这种情况。一些浏览器从不报告 0 或 1 而直接从 2 开始,然后是 3 和 4。其他浏览器则报告所有的状态。还有一些则多次报告就绪状态 1。在上一节中看到,服务器多次调用 updatePage(),每次调用都会弹出警告框 —— 可能和预期的不同!

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

    HTTP 状态码:

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

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

         因此除了就绪状态外,还需要检查 HTTP 状态。我们期望的状态码是 200,它表示一切顺利。如果就绪状态是 4 而且状态码是 200,就可以处理服务器的数据了,而且这些数据应该就是要求的数据(而不是错误或者其他有问题的信息)。因此还要在回调方法中增加状态检查,如下所示:

     function updatePage() {
         if (request.readyState == 4)//检查HTTP就绪状态
           if (request.status == 200)//检查HTTP状态码
             alert("Server is done!");
       }

    读取响应文本:

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

          关于 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[0] 访问,被设置为 ID 为 “order” 的字段的值。第二个值 response[1],即客户地址,则需要更多一点处理。因为地址中的行用一般的行分隔符(“\n”字符)分隔,代码中需要用 XHTML 风格的行分隔符 <br /> 来代替。替换过程使用replace() 函数和正则表达式完成。最后,修改后的文本作为 HTML 表单 div 中的内部 HTML。结果就是表单突然用客户信息更新了。

     

    参考:http://www.ibm.com/developerworks/cn/xml/wa-ajaxintro2/

     

     

     

     

     

  • 相关阅读:
    Vue.Js(html5) + Java实现文件分片上传
    进程、线程基础知识全家桶,30 张图一套带走
    20 张图揭开「内存管理」的迷雾,瞬间豁然开朗
    面试官:换人!他连 TCP 这几个参数都不懂
    TCP 半连接队列和全连接队列满了会发生什么?又该如何应对?
    实战!我用 Wireshark 让你“看得见“ TCP
    IP 基础知识全家桶,45 张图一套带走
    写了Bug,误执行 rm -fr /*,我删删删删库了,要跑路吗?
    你还在为 TCP 重传、滑动窗口、流量控制、拥塞控制发愁吗?看完图解就不愁了
    硬不硬你说了算!35 张图解被问千百遍的 TCP 三次握手和四次挥手面试题
  • 原文地址:https://www.cnblogs.com/zxpgo/p/2571040.html
Copyright © 2020-2023  润新知