《JavaScript高级程序设计》Chapter 12 Ajax与Comet
Chapter 21 Ajax与Comet
- Ajax:Asynchronous JavaScript + XML
- 然而重点并不在于处理数据格式(不仅限于处理XML),而是无需刷新或者卸载整个页面就可以向服务器请求格外的数据并且取得这个数据。(然后就可以用DOM处理这些数据了)。
- 在没有Ajax这个观点提出来之前,其实已经能够实现。这个是个事实标准而已。
- 核心:XMLHttpRequest对象(XHR对象),将浏览器原生的通信能力提供给开发人员。Ajax的流程基本围绕着这个对象实现。
XMLHttpRequest对象
创建XMLHttpRequest对象
- IE5及之前版本(旧版本):XHR对象通过MSXML库中的ActiveX对象实现,会遇到三个不同的版本:MSXML2.XMLHttp、MSXML2.XMLHttp.3.0、MSXML2.XMLHttp.6.0。因此依考MSXML库创建XMLHttpRequest对象,需要检查检查三个版本哪一个可用,然后赋给arguments.callee.activeXString,进而通过new ActiveXObject(activeXString)创建。
- IE7及更高版本、其他浏览器:通过原生的XHR实现,即通过new XMLHttpRequest()创建
- 可以按照上述情况做一个简单的能力检测函数。
XHR的用法(一般流程)
- 创建XHR对象:方法同上。
- 调用open()方法,启动一个请求以备发送(而不是真正发送了这个请求。传入3个参数:发送请求的类型("get","post")、请求的URL、是否异步发送请求的布尔值。注意只能向“同一个域、同一个端口、同一个协议”的URL发送请求(如果需要跨域,看后面的跨域技术部分)。
- 调用send()方法,发送特定的请求:如果不需要传输数据,则仍要send(null)形式传入null参数。
- 检查响应状态:
a. 请求同步的时候:JS会等服务器相应后再继续执行,接到响应后,响应的数据会自动填充XHR对象的属性(responseText/responseXML/status/statusText)。接到响应后,第一步是检查status属性(xhr.status>=200 && xhr.status<300)||xhr.status == 304.
b.发送异步请求的时候:检测XHR对象的readyState属性。只要readyState属性值从一个变成另一个,都会触发一次readystatechange事件(一般考虑值为4的情况)。而一般在open()方法前 - Abort()方法取消异步请求。且注意对XHR对象进行解除引用的操作。不建议重用XHR对象。
HTTP头部信息(流程中还应该处理的)
- 处理HTTP请求或者响应的相应头部信息。
- 可以通过setRequestHeader()方法设置自定义的请求头部信息。
- 并且建议这么做,注意这个设置放在调用send()之前。
- getResponseHeader()/getAllResponseHeaders()方法获取相应的响应头部信息。
- 服务器端可以用头部信息向浏览器发送数据。
GET请求
- 常用于向服务器查询信息。
- 需要将这些信息附加到URL的末尾。
- 查询字符串有严格的格式,需要经过encodeURIComponent()对每个名和值进行处理,然后构造出特定的URL格式:例如:"example.php?name1=value1&name2=value2"
- 当然GET请求的初始化通过open()方法,这时的URL就是经过处理的URL了。
POST请求
- 向服务器发送应该被保存的数据。通常数据是请求的主体,且数据量大、格式不限。所以需要经过必要的处理。
- 服务器对POST请求和提交Web表单的请求不会一视同仁(而我们需要它能统一处理),服务器一般会读取发送过来的原始数据解析其中有用的部分。所以我们可以用XHR来模仿表单的提交:
a. Content-Type头部信息应该设置为application/x-www-form-urlencoded
b. 然后以适当的个数格式创建字符串,用serialize()对表单进行序列化。
c. 最后以send()方法将上述经序列化处理的字符串发送。 - 显然POST请求消耗的资源比GET的多、当然速度会慢。
XMLHttpRequest 2级
- XMLHttpRequest 1级描述XHR对象实现的基本流程,XMLHttpRequest 2级进一步对其发展。
FormData
- 创建专门的FormData类型,以简化上面提到过的POST请求的时候修改头部信息、序列化表单的操作。
- New FormData()创建相应的对象,传入待发送的表单数据,最后调用send()方法将其发送即可。
- 主要是免去了处理头部信息的步骤。
超时设定
- timeout属性:设置毫秒值。当经过这段时间没有得到相应则调用ontimeout事件处理程序。
overrideMimeType()方法
- 顾名思义,重写服务器返回的MIME类型。
- 在send()被调用之前使用。
进度事件
- 6个进度事件
- 每个请求都从触发loadstart事件开始,接下来是一个或者多个progress事件,然后根据情况触发error/abort/load事件中的一个,最后以触发loadend事件结束。
- load事件:FireFox用以简化异步交互的模型,代替readystatechange事件。然而浏览器只要收到服务器的响应,不管其状态都会触发load事件,所以仍然需要检查status属性。
- progress事件:在接收数据期间周期性触发,有三个额外的属性:lengthComputable/position/totalSize,可以用来创建进度指示器。这个事件与onload事件、onreadystatechange事件处理程序一样,需要在open()方法前添加。
跨域资源
- 用XHR试想Ajax通信的主要限制:跨域安全限制。
- CORS定义了当必须实现跨域访问的时候,浏览器和服务器应该如何沟通。基本思想就是用自定义的HTTP头部让浏览器和服务器进行沟通,从而决定请求和响应是成功还是失败(判断两边的对应参数是否匹配,有点像设备间的蓝牙匹配)。
- 浏览器Origin头部、服务器Access-Control-Allow-Origin头部
- 简单处理的情况下,请求和响应都不包含cookie信息。
IE对CORS的实现:
- XDR类型:类似XHR类型
- 它的open()方法只几首两个参数:请求类型和URL
- 只进行异步请求
其他浏览器对CORS的实现
- WebKit通过XMLHttpRequest对象实现了对CORS的原生支持
- 无需额外编写代码就可以触发这个行为,只要在open()方法中传入绝对URL即可。(也就是说会自动进行处理)
Preflighted Requests
带凭据的请求(凭据:cookie、HTTP认证、客户端SSL证明等。简单跨域处理不带)
其他跨域技术
- 图像Ping、JSONP、Comet(长轮询、HTTP流)、Web Sockets
- 图像Ping和JSONP是另外两种跨域通信的技术,但不如CORS稳妥。
- Comet是对Ajax的进一步扩展,让服务器几乎能够实时地向客户端推送数据。实际上重点在服务器向浏览器的推送。
- Web Sockets是一种与服务器进行全双工、双向通信的信道,不适用HTTP协议。