1 简介

Ajax与Comet - 图1

2005年,Jesse James Garrett发表了一篇在线文章,题为“Ajax:A new Approach to Web Application”。他在这篇文章里介绍了一种技术,用他的话说,就叫Ajax,是对Asynchronous JavaScript + XML 的简写。这一技术能够向服务器请求额外的数据而无需卸载页面,会带来更好的用户体验。
Ajax技术的核心是XMLHttpRequest对象(简称XHR),XHR为向服务器发送请求和解析服务器响应提供了流畅的接口。能够以异步方式从服务器取得更多信息,意味着用户单机后,可以不必刷新页面也能取得新数据。也就是说,可以使用XHR对象取得新数据,然后再通过DOM将新数据插入到页面中。另外,虽然名字包含XML的成分,但Ajax通信与数据格式无关;这种技术就是无须刷新页面即可从服务器取得数据,但不一定是XML数据。

2 XMLHTTPRequest对象

Ajax与Comet - 图2
创建方法:Ajax与Comet - 图3

XHR的用法

使用XHR对象是,要调用的第一个方法是open()
它接受3个参数;要发送的请求的类型(get、post等)、请求的URL和表示是否异步发送请求的布尔值。
Ajax与Comet - 图4
有关这行代码,需要说明两点:
一是URL相对于执行代码的当前页面(当然也可以使用绝对路径);二是调用open()方法并不会真正发送请求,而只是移动一个请求以备发送。
要发送特定的请求,必须向下面这样调用send()方法:
Ajax与Comet - 图5
这里的send()方法接收一个参数,即要作为请求主体发送的数据。如果不需要通过请求主体发送数据,则必须传入null,因为这个参数对有些浏览器来说是必需的。调用send()之后,请求就会被分派到服务器。
由于这次请求是同步的,JavaScript代码会等到服务器响应之后再继续执行。在收到响应后,响应的数据会自动填充XHR对象的属性,相关的属性简介如下。

  • responseText:作为响应主体被返回的文本。
  • responseXML:如果响应的内容类型是“text/xml”或“application/xml”,这个属性中将保存包含响应数据的XML DOM文档。
  • status:响应的HTTP状态。
  • statusText:HTTP状态的说明。

Ajax与Comet - 图6

3 readyState属性

像前面这样发送同步请求当然没有问题,但多数情况下,我们还是要发送异步请求,才能让JavaScript继续执行而不必等待响应。此时,可以检测XHR对象的readyState属性,该属性表示请求/响应过程的当前活动阶段。这个属性可取的值如下。

  • 0:未初始化。尚未调用open()方法。
  • 1:启动。已经调用open()方法,但尚未调用send()方法。
  • 2:发送。已经调用send()方法,但尚未接收到响应。
  • 3:接收。已经接收到部分响应数据。
  • 4:完成。已经接收到全部响应数据,而且已经可以在客户端使用了。

只要readyState属性的值由一个值变成另一个值,都会触发一次readystatechange事件。可以利用这个事件监测每次状态变化后readyState的值。通常,我们只对readyState值为4的阶段感兴趣,因为这时所有数据都已经就绪。不过,必须在调用open()之前指定onreadystatechange事件处理程序才能确保跨浏览器兼容性。

例子:
Ajax与Comet - 图7
Ajax与Comet - 图8

4 abort方法取消异步请求

另外,在接收到响应之前还可以调用abort()方法来取消异步请求,如下所示:
xhr.abort();
调用这个方法后,XHR对象会停止触发事件,而且也不再允许访问任何与响应有关的对象属性。在终止请求之后,还应该对XHR对象进行引用操作。由于内存原因,不建议重用XHR对象。

HTTP头部信息

每个HTTP请求和响应都会带有相应的头部信息,其中有的对开发人员有用,有的也没有什么用。XHR对象也提供了操作者两种头部(即请求头部响应头部)信息的方法。
默认情况下,在发送XHR请求的同时,还会发送下列头部信息。

  • Accept:浏览器能够处理的内容类型。
  • Accept-Charset:浏览器能够显示的字符集。
  • Accept-Encoding:浏览器能够处理的压缩编码。
  • Accept-Language:浏览器当前设置的语言。
  • Connection:浏览器与服务器之间连接的类型。
  • Cookie:当前页面设置的任何Cookie。
  • Host:发出请求的页面所在的域。
  • Referer:发出请求的页面的URI。注意,HTTP规范将这个头部字段拼写错了,而为保证与规范一致,也只能将错就错了。(这个英文单词的正确拼法应该是referrer)
  • User-Agent:浏览器的用户代理字符串。

查看header头文件信息的方法。
Ajax与Comet - 图9
虽然不同浏览器实际发送的头部信息会有所不同,但以上列出的基本上是所有浏览器都会发送的。使用setRequestHeader()方法可以设置自定义的请求头部信息。这个方法接受两个参数:头部字段的名称和头部字段的值。要成功发送请求头部信息,必须在调用open()方法之后且调用send()方法之前调用setRequestHeader()。
例子
Ajax与Comet - 图10

服务器在接收到这种自定义的头部信息之后,可以执行相应的后续操作。我们建议读者使用自定义的头部字段名称,不要使用浏览器正常发送的字段名称,否则有可能会影响服务器的响应。有的浏览器允许开发人员重写默认的头部信息,但有的浏览器则不允许这样做。
调用XHR对象的getResponseHeader()方法并传入头部字段名称,可以取得相应的响应头部信息。而调用getAllResponseHeaders()方法则可以取得一个包含所有头部信息的长字符串。如图:
Ajax与Comet - 图11
这种格式化的输出可以方便我们检查响应中所有头部字段的名称,而不必一个一个的检查某个字段是否存在。

GET请求

GET是最常见的请求类型,最常用于向服务器查询某些信息。必要时,可以将查询字符串参数追加到URL的末尾,以便将信息发送给服务器。对XHR而言,位于传入open()方法的URL末尾的查询字符串必须经过正确的编码才行。
使用GET请求经常会发生的一个错误,就是查询字符串的格式有问题。查询字符串中每个参数的名称和值都必须使用encodeURIComponent()进行编码,然后才能放到URL的末尾;而且所有名-值对儿必须由和号(&)分割。如图所示
Ajax与Comet - 图12

5 addURLparam函数(添加URL参数)

下面这个函数可以辅助向现有URL的末尾添加查询字符串参数:
function addURLParam(url, name, value) {
url += (url.indexOf(“?”) == -1 ? “?” : “&”);
url += encodeURIComponent(name) + “=” + encodeURIComponent(value);
return url;
}
Ajax与Comet - 图13

POST请求

使用频率仅次于GET的是POST请求,通常用于向服务器发送应该被保存的数据。POST请求应该把数据作为请求的主体提交,而GET请求传统上不是这样。POST请求的主体可以包含非常多的数据,而且格式不限。在open()方法第一个参数的位置传入post,就可以初始化一个POST请求,如下面的例子所示。
xhr.open(‘post’,’example.php’,true)
发送POST请求的第二步就是向send()方法中传入某些数据。由于XHR最初的设计主要是为了处理XML,因此可以在此传入XML DOM文档,传入的文档经序列化之后将作为请求主体被提交到服务器。当然,也可以在此传入任何想发送到服务器的字符串。
Ajax与Comet - 图14
Ajax与Comet - 图15

6 serialize()序列化表单

每写,可以参考书中14章序列化。或百度获取序列化函数代码。待更新

7 XMLHttpRequest2级

XMLHttpRequest1级只是把已有的XHR对象的实现细节描述了出来。而XMLHttpRequest2级则进一步发展了XHR。并非所有浏览器都完整地实现了XMLHttpReque2级规范,但所有浏览器都实现了它规定的部分内容。

8 FormData

FormData方便序列化 表单。
Ajax与Comet - 图16
Ajax与Comet - 图17
Ajax与Comet - 图18
Ajax与Comet - 图19

超时设定

IE8为XHR对象添加了一个timeout属性,表示请求等待响应多少秒之后就终止。在给tiemout设置一个数值后,如果在规定的时间内浏览器没有接收到响应,那么就会触发timeout事件,进而会调用ontimeout事件处理程序。这项功能后来也被收入了XMLHttpRequest2级规范中。
实例
Ajax与Comet - 图20
Ajax与Comet - 图21

overrideMimeType()方法

Ajax与Comet - 图22

9 进度事件

Ajax与Comet - 图23

10 Load事件

Ajax与Comet - 图24
Ajax与Comet - 图25

progress事件

Ajax与Comet - 图26
Ajax与Comet - 图27
Ajax与Comet - 图28
Ajax与Comet - 图29

11 跨源资源共享

通过XHR实现Ajax通信的一个主要限制,来源于跨域安全策略。默认情况下,XHR对象只能访问与包含它的页面位于同一个域中的资源。这种安全策略可以预防某些恶意行为。但是,实现合理的跨域请求对开发某些浏览器应用程序也是至关重要。
CORS(Cross-Origin Resource Sharing,跨源资源共享)是W3C的一个工作草案,定义了在必须访问跨源资源时,浏览器与服务器应该如何沟通。CORS背后的基本思想,就是使用自定义的HTTP头部让浏览器与服务器进行沟通,从而决定请求或响应是应该成功,还是应该失败。
更多案例参考:https://www.w3cschool.cn/javascript_guide/javascript_guide-z4jy26a3.html
与JSONP的比较
CORS与JSONP的使用目的相同,但是比JSONP更强大。
JSONP只支持GET请求,CORS支持所有类型的HTTP请求。JSONP的优势在于支持老式浏览器,以及可以向不支持CORS的网站请求数据。

12 其他跨域技术

在CORS出现以前,要实现跨域Ajax通信颇费一些周折。开发人员想出了一些办法,利用DOM中能够执行跨域请求的功能,在不依赖XHR对象的情况下也能发送某种请求。虽然CORS技术已经无处不在,但开发人员之间发明的这些技术仍然被广泛使用,毕竟这样不需要修改服务器端代码。
Ajax与Comet - 图30
Ajax与Comet - 图31