Ajax 简介

来源:互联网 发布:大数据时代有什么用 编辑:程序博客网 时间:2024/06/05 21:54
 

Ajax

 

1.       获取 XMLHttpRequest 对象

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

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

 

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

 

很容易被这些花括号迷住了眼睛,因此下面分别介绍每一步:

1.       创建一个新变量 request 并赋值 false。使用 false 作为判断条件,它表示还没有创建 XMLHttpRequest 对象。

2.       增加 try/catch 块:

1.       尝试创建 XMLHttpRequest 对象。

2.       如果失败(catch (trymicrosoft)):

1.       尝试使用较新版本的 Microsoft 浏览器创建 Microsoft 兼容的对象(Msxml2.XMLHTTP)。

2.       如果失败(catch (othermicrosoft))尝试使用较老版本的 Microsoft 浏览器创建 Microsoft 兼容的对象(Microsoft.XMLHTTP)。

3.       如果失败(catch (failed))则保证 request 的值仍然为 false

3.       检查 request 是否仍然为 false(如果一切顺利就不会是 false)。

4.       如果出现问题(request false)则使用 JavaScript 警告通知用户出现了问题。

 

2.  Ajax 发出请求

接下来就是在所有 Ajax 应用程序中基本都雷同的流程:

1.       Web 表单中获取需要的数据。

2.       建立要连接的 URL

3.       打开到服务器的连接。

4.       设置服务器在完成后要运行的函数。

5.       发送请求。

打开请求

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

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

 

3. 处理服务器响应

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

  • 0:请求没有发出(在调用 open() 之前)。
  • 1:请求已经建立但还没有发出(调用 send() 之前)。
  • 2:请求已经发出正在处理之中(这里通常可以从响应得到内容头部)。
  • 3:请求已经处理,响应中通常有部分数据可用,但是服务器还没有完成响应。
  • 4:响应已完成,可以访问服务器响应并使用它。
 
   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, "<br />");
       } else if (request.status == 404) {
         alert ("Requested URL is not found.");
       } else if (request.status == 403) {
         alert("Access denied.");
       } else
         alert("status is " + request.status);
     }
   }

因此您的工作就不能仅仅局限于简单的应用程序了,而是需要更深入理解 XMLHttpRequest

  • 如果您可以考虑各种就绪状态 —— 并且理解了这些就绪状态在不同浏览器之间的区别 —— 就可以快速调试应用程序了。您甚至可以基于就绪状态而开发一些创造性的功能,并向用户和客户回报请求的状态。
  • 如果您要对状态代码进行控制,就可以设置应用程序来处理脚本错误、非预期的响应以及边缘情况。结果是应用程序在所有的时间都可以正常工作,而不仅仅是只能一切都正常的情况下才能运行。
  • 增加这种生成 HEAD 请求的能力,检查某个 URL 是否存在,以及确认某个文件是否被修改过,这样就可以确保用户可以获得有效的页面,用户所看到的信息都是最新的,(最重要的是)让他们惊讶这个应用程序是如何健壮和通用。

对于 XML 最好使用 POST 请求,因为有些浏览器限制了 GET 请求字符串的长度,而 XML 可能很长,可以看到清单 2 中把 GET 改成了 POST 方法。

 

JSON 基础

简单地说,JSON 可以将 JavaScript 对象中表示的一组数据转换为字符串,然后就可以在函数之间轻松地传递这个字符串,或者在异步应用程序中将字符串从 Web 客户机传递给服务器端程序。这个字符串看起来有点儿古怪(稍后会看到几个示例),但是 JavaScript 很容易解释它,而且 JSON 可以表示比名称/值对更复杂的结构。例如,可以表示数组和复杂的对象,而不仅仅是键和值的简单列表。

简单 JSON 示例

按照最简单的形式,可以用下面这样的 JSON 表示名称/值对:

{ "firstName": "Brett" }

 

这个示例非常基本,而且实际上比等效的纯文本名称/值对占用更多的空间:

firstName=Brett

 

但是,当将多个名称/值对串在一起时,JSON 就会体现出它的价值了。首先,可以创建包含多个名称/值对的记录,比如:

{ "firstName": "Brett", "lastName":"McLaughlin", "email": "brett@newInstance.com" }

 

从语法方面来看,这与名称/值对相比并没有很大的优势,但是在这种情况下 JSON 更容易使用,而且可读性更好。例如,它明确地表示以上三个值都是同一记录的一部分;花括号使这些值有了某种联系。

值的数组

当需要表示一组值时,JSON 不但能够提高可读性,而且可以减少复杂性。例如,假设您希望表示一个人名列表。在 XML 中,需要许多开始标记和结束标记;如果使用典型的名称/值对(就像在本系列前面文章中看到的那种名称/值对),那么必须建立一种专有的数据格式,或者将键名称修改为 person1-firstName 这样的形式。

如果使用 JSON,就只需将多个带花括号的记录分组在一起:

{ "people": [

  { "firstName": "Brett", "lastName":"McLaughlin", "email": "brett@newInstance.com" },

  { "firstName": "Jason", "lastName":"Hunter", "email": "jason@servlets.com" },

  { "firstName": "Elliotte", "lastName":"Harold", "email": "elharo@macfaq.com" }

]}

 

这不难理解。在这个示例中,只有一个名为 people 的变量,值是包含三个条目的数组,每个条目是一个人的记录,其中包含名、姓和电子邮件地址。上面的示例演示如何用括号将记录组合成一个值。当然,可以使用相同的语法表示多个值(每个值包含多个记录):

{ "programmers": [

  { "firstName": "Brett", "lastName":"McLaughlin", "email": "brett@newInstance.com" },

  { "firstName": "Jason", "lastName":"Hunter", "email": "jason@servlets.com" },

  { "firstName": "Elliotte", "lastName":"Harold", "email": "elharo@macfaq.com" }

 ],

"authors": [

  { "firstName": "Isaac", "lastName": "Asimov", "genre": "science fiction" },

  { "firstName": "Tad", "lastName": "Williams", "genre": "fantasy" },

  { "firstName": "Frank", "lastName": "Peretti", "genre": "christian fiction" }

 ],

"musicians": [

  { "firstName": "Eric", "lastName": "Clapton", "instrument": "guitar" },

  { "firstName": "Sergei", "lastName": "Rachmaninoff", "instrument": "piano" }

 ]

}

 

这里最值得注意的是,能够表示多个值,每个值进而包含多个值。但是还应该注意,在不同的主条目(programmersauthors musicians)之间,记录中实际的名称/值对可以不一样。JSON 是完全动态的,允许在 JSON 结构的中间改变表示数据的方式。

在处理 JSON 格式的数据时,没有需要遵守的预定义的约束。所以,在同样的数据结构中,可以改变表示数据的方式,甚至可以以不同方式表示同一事物。

JavaScript 中使用 JSON

掌握了 JSON 格式之后,在 JavaScript 中使用它就很简单了。JSON JavaScript 原生格式,这意味着在 JavaScript 中处理 JSON 数据不需要任何特殊的 API 或工具包。

JSON 数据赋值给变量

例如,可以创建一个新的 JavaScript 变量,然后将 JSON 格式的数据字符串直接赋值给它:

var people =

  { "programmers": [

    { "firstName": "Brett", "lastName":"McLaughlin", "email": "brett@newInstance.com" },

    { "firstName": "Jason", "lastName":"Hunter", "email": "jason@servlets.com" },

    { "firstName": "Elliotte", "lastName":"Harold", "email": "elharo@macfaq.com" }

   ],

  "authors": [

    { "firstName": "Isaac", "lastName": "Asimov", "genre": "science fiction" },

    { "firstName": "Tad", "lastName": "Williams", "genre": "fantasy" },

    { "firstName": "Frank", "lastName": "Peretti", "genre": "christian fiction" }

   ],

  "musicians": [

    { "firstName": "Eric", "lastName": "Clapton", "instrument": "guitar" },

    { "firstName": "Sergei", "lastName": "Rachmaninoff", "instrument": "piano" }

   ]

  }

 

这非常简单;现在 people 包含前面看到的 JSON 格式的数据。但是,这还不够,因为访问数据的方式似乎还不明显。

访问数据

尽管看起来不明显,但是上面的长字符串实际上只是一个数组;将这个数组放进 JavaScript 变量之后,就可以很轻松地访问它。实际上,只需用点号表示法来表示数组元素。所以,要想访问 programmers 列表的第一个条目的姓氏,只需在 JavaScript 中使用下面这样的代码:

people.programmers[0].lastName;

 

注意,数组索引是从零开始的。所以,这行代码首先访问 people 变量中的数据;然后移动到称为 programmers 的条目,再移动到第一个记录([0]);最后,访问 lastName 键的值。结果是字符串值 “McLaughlin”

下面是使用同一变量的几个示例。

people.authors[1].genre                          // Value is "fantasy"

 

people.musicians[3].lastName                     // Undefined. This refers to the fourth entry,

 and there isn't one

 

people.programmers.[2].firstName     // Value is "Elliotte"

 

利用这样的语法,可以处理任何 JSON 格式的数据,而不需要使用任何额外的 JavaScript 工具包或 API

修改 JSON 数据

正如可以用点号和括号访问数据,也可以按照同样的方式轻松地修改数据:

people.musicians[1].lastName = "Rachmaninov";

 

在将字符串转换为 JavaScript 对象之后,就可以像这样修改变量中的数据。

转换回字符串

当然,如果不能轻松地将对象转换回本文提到的文本格式,那么所有数据修改都没有太大的价值。在 JavaScript 中这种转换也很简单:

String newJSONtext = people.toJSONString();

 

这样就行了!现在就获得了一个可以在任何地方使用的文本字符串,例如,可以将它用作 Ajax 应用程序中的请求字符串。

更重要的是,可以将任何 JavaScript 对象转换为 JSON 文本。并非只能处理原来用 JSON 字符串赋值的变量。为了对名为 myObject 的对象进行转换,只需执行相同形式的命令:

String myObjectInJSON = myObject.toJSONString();

 

这就是 JSON 与本系列讨论的其他数据格式之间最大的差异。如果使用 JSON,只需调用一个简单的函数,就可以获得经过格式化的数据,可以直接使用了。对于其他数据格式,需要在原始数据和格式化数据之间进行转换。即使使用 Document Object Model 这样的 API(提供了将自己的数据结构转换为文本的函数),也需要学习这个 API 并使用 API 的对象,而不是使用原生的 JavaScript 对象和语法。

最终结论是,如果要处理大量 JavaScript 对象,那么 JSON 几乎肯定是一个好选择,这样就可以轻松地将数据转换为可以在请求中发送给服务器端程序的格式。

结束语

本系列中的下一篇文章将讨论发送数据以外的问题,深入介绍服务器端程序如何接收和处理 JSON 格式的数据。还要讨论服务器端程序如何跨脚本和服务器端组件以 JSON 格式发送回数据,这样就可以将 XML、纯文本和 JSON 请求和响应混合在一起。这可以提供很大的灵活性,可以按照几乎任何组合结合使用所有这些工具。

JSON 是适用于 Ajax 应用程序的一种有效格式,原因是它使 JavaScript 对象和字符串值之间得以快速转换。

 

JSON 发给服务器

JSON 发给服务器并不难,但却至关重要,而且还有一些重要的选择要做。但是,一旦决定使用 JSON,所要做的这些选择就会十分简单而且数量有限,所以您需要考虑和关注的事情不多。重要的是能够将 JSON 字符串发送给服务器,而且最好能做到尽快和尽可能简单。

通过 GET 以名称/值对发送 JSON

JSON 数据发给服务器的最简单方法是将其转换成文本,然后以名称/值对的值的方式进行发送。请务必注意,JSON 格式的数据是相当长的一个对象,看起来可能会如清单 1 所示:


清单 1. JSON 格式的简单 JavaScript 对象

               

var people =  { "programmers": [    { "firstName": "Brett", "lastName":"McLaughlin",

"email": "brett@newInstance.com" },    { "firstName": "Jason", "lastName":"Hunter",

"email": "jason@servlets.com" },    { "firstName": "Elliotte", "lastName":"Harold",

"email": "elharo@macfaq.com" }   ],  "authors": [    { "firstName": "Isaac",

"lastName": "Asimov", "genre": "science fiction" },    { "firstName": "Tad",

"lastName": "Williams", "genre": "fantasy" },    { "firstName": "Frank",

"lastName": "Peretti", "genre": "christian fiction" }   ],  "musicians": [   

{ "firstName": "Eric", "lastName": "Clapton", "instrument": "guitar" },  

{ "firstName": "Sergei", "lastName": "Rachmaninoff", "instrument": "piano" }   ]  }

 

如果要以名称/值对将其发送到服务器端,应该如下所示:

var url = "organizePeople.php?people=" + people.toJSONString();

xmlHttp.open("GET", url, true);

xmlHttp.onreadystatechange = updatePage;

xmlHttp.send(null);

 

这看起来不错,但却存在一个问题:在 JSON 数据中会有空格和各种字符,Web 浏览器往往要尝试对其继续编译。要确保这些字符不会在服务器上(或者在将数据发送给服务器的过程中)引起混乱,需要在 JavaScript escape() 函数中做如下添加:

var url = "organizePeople.php?people=" + escape(people.toJSONString());

request.open("GET", url, true);

request.onreadystatechange = updatePage;

request.send(null);

 

该函数可以处理空格、斜线和其他任何可能影响浏览器的内容,并将它们转换成 Web 可用字符(比如,空格会被转换成 %20,浏览器并不会将其视为空格处理,而是不做更改,将其直接传递到服务器)。之后,服务器会(通常自动)再把它们转换回它们传输后的本来面目

这种做法的缺点有两个:

  • 在使用 GET 请求发送大块数据时,对 URL 字符串有长度限制。虽然这个限制很宽泛,但对象的 JSON 字符串表示的长度可能超出您的想象,尤其是在使用极其复杂的对象时更是如此。
  • 在跨网络以纯文本发送所有数据的时候,发送数据面临的不安全性超出了您的处理能力。

简言之,以上是 GET 请求的两个限制,而不是简单的两个与 JSON 数据相关的事情。在想要发送用户名和姓之外的更多内容,比如表单中的选择时,二者可能会需要多加注意。若要处理任何机密或极长的内容,可以使用 POST 请求。

利用 POST 请求发送 JSON 数据

当决定使用 POST 请求将 JSON 数据发送给服务器时,并不需要对代码进行大量更改,如下所示:

var url = "organizePeople.php?timeStamp=" + new Date().getTime();

request.open("POST", url, true);

request.onreadystatechange = updatePage;

request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");

request.send(people.toJSONString());

 

这些代码中的大部分,您都在 掌握 Ajax,第 3 部分Ajax 中的高级请求和响应中见过,应该比较熟悉,第 3 部分重点介绍了如何发送 POST 请求。请求使用 POST 而非 GET 打开,而且 Content-Type 头被设置为让服务器预知它能得到何种数据。在这种情况下,即为 application/x-www-form-urlencoded,它让服务器知道现在发送的是文本,正如它从常规的 HTML 表单中得到的一样。

另一个简单提示是 URL 的末尾追加了时间。这就确保了请求不会在它第一次被发送后即缓存,而是会在此方法每次被调用后重新创建和重发;此 URL 会由于时间戳的不同而稍微有些不同。这种技巧常被用于确保到脚本的 POST 每次都会实际生成新请求且 Web 服务器不会尝试缓存来自服务器的响应。

JSON 就只是文本

不管使用 GET 还是 POST,关键之处在于 JSON 就只是文本。由于不需要特殊编码而且每个服务器端脚本都能处理文本数据,所以可以轻松利用 JSON 并将其应用到服务器。假如 JSON 是二进制格式的或是一些怪异的文本编码,情况就不这么简单了;幸好 JSON 只是常规的文本数据(正如脚本能从表单提交中所接收到的数据,在 POST 段和 Content-Type 头中亦可以看出),所以在将数据发送到服务器时无需太费心。

在服务器上解释 JSON

一旦您编写完客户端 JavaScript 代码、允许用户与 Web 表单和 Web 页的交互、收集发送给服务器端程序以做处理所需的信息,此时,服务器就成为了应用程序(如果调用了异步使用的服务器端程序,则可能是我们认为的所谓的 “Ajax 应用程序)中的主角。在此时,您在客户端所做的选择(比如使用 JavaScript 对象,然后将其转换成 JSON 字符串)必须要与服务器端的选择相匹配,比如使用哪个 API 解码 JSON 数据。

处理 JSON 的两步骤

不管在服务器端使用何种语言,在服务器端处理 JSON 基本上就需要两个步骤。

1.       针对编写服务器端程序所用的语言,找到相应的 JSON 解析器/工具箱/帮助器 API

2.       使用 JSON 解析器/工具箱/帮助器 API 取得来自客户机的请求数据并将数据转变成脚本能理解的东西。

以上差不多就是目前所应了解的大致内容了。接下来,我们对每个步骤进行较为详细的介绍。

寻找 JSON 解析器

寻找 JSON 解析器或工具箱最好的资源是 JSON 站点(有关链接,请参阅 参考资料)。在这里,除了可以了解此格式本身的方方面面之外,还可以通过各种链接找到 JSON 的各种工具和解析器,从 ASP Erlang,到 Pike,再到 Ruby,应有尽有。您只需针对自己编写脚本所用的语言下载相应的工具箱即可。为了让服务器端脚本和程序能够使用此工具箱,可以根据情况对其进行选择、扩展或安装(如果在服务器端使用的是 C#PHP Lisp,则可变性更大)。

例如,如果使用的是 PHP,可以简单将其升级至 PHP 5.2 并用它完成操作;在 PHP 这个最新版本默认包含了 JSON 扩展。实际上,那也是在使用 PHP 时处理 JSON 的最好方法。如果使用的是 Java servletjson.org 上的 org.json 包显然就是个不错的选择。在这种情况下,可以从 JSON Web 站点下载 json.zip 并将其中包含的源文件添加到项目构建目录。编译完这些文件后,一切就就绪了。对于所支持的其他语言,同样可以使用相同的步骤;使用何种语言取决于您对该语言的精通程度,最好使用您所熟悉的语言。

使用 JSON 解析器

一旦获得了程序可用的资源,剩下的事就是找到合适的方法进行调用。比如,假设为 PHP 使用的是 JSON-PHP 模板:

// This is just a code fragment from a larger PHP server-side script

require_once('JSON.php');

 

$json = new Services_JSON();

 

// accept POST data and decode it

$value = $json->decode($GLOBALS['HTTP_RAW_POST_DATA']);

 

// Now work with value as raw PHP

 

通过该模板,可将获得的所有数据(数组格式的、多行的、单值的或 JSON 数据结构中的任何内容)转换成原生 PHP 格式,放在 $value 变量中。

如果在 servlet 中使用的是 org.json 包,则会使用如下代码:

public void doPost(HttpServletRequest request, HttpServletResponse response)

  throws ServletException, IOException {

 

  StringBuffer jb = new StringBuffer();

  String line = null;

  try {

    BufferedReader reader = request.getReader();

    while ((line = reader.readLine()) != null)

      jb.append(line);

  } catch (Exception e) { //report an error }

 

  try {

    JSONObject jsonObject = new JSONObject(jb.toString());

  } catch (ParseException e) {

    // crash and burn

    throw new IOException("Error parsing JSON request string");

  }

 

  // Work with the data using methods like...

  // int someInt = jsonObject.getInt("intParamName");

  // String someString = jsonObject.getString("stringParamName");

  // JSONObject nestedObj = jsonObject.getJSONObject("nestedObjName");

  // JSONArray arr = jsonObject.getJSONArray("arrayParamName");

  // etc...

}

结束语

至此,您应该从技术角度对如何在服务器端处理 JSON 有了基本的把握。本篇文章和本系列的 10 部分 不仅提供了技术层面的帮助,而且还向您展示了 JSON 是一种多么灵活、强大的数据格式。即使您不会在每个应用程序中都使用 JSON,但优秀的 Ajax JavaScript 程序员的工具箱中总少不了 JSON 以备不时之需。

我当然很希望能够分享您的 JSON 使用经验以及您对何种语言更善于在服务器端处理 JSON 数据的高见。您可以访问 Java XML 新闻组(有关链接,请参阅 参考资料 部分)跟我联系。享受 JSON 和文本数据格式的乐趣吧。