Ajax 与 Comet
Ajax技术的核心是 XMLHttpRequest 对象(简称 XHR)。能够以异步方式从服务器取得更多信息,意味着用户单击后,可以不必刷新页面也能取得新数据。 也就是说,可以使用 XHR 对象取得新数据,然后再通过 DOM 将新数据插入到页面中。
XMLHttpRequest 对象
var xhr = new XMLHttpRequest();
- XHR的用法
- 在使用 XHR 对象时,要调用的第一个方法是 open()方法
- 它接受 3 个参数:
- 要发送的请求的类型 ("get"、"post"等)
- 请求的 URL
- 表示是否异步发送请求的布尔值。(false是同步)
xhr.open("get", "example.php", false);
这行代码会启动一个针对 example.php 的 GET 请求。
有关这行代码,需要说明两点:
一是 URL 相对于执行代码的当前页面(当然也可以使用绝对路径);
二是调用 open()方法并不会真正发送请求, 而只是启动一个请求以备发送。
- 要发送特定的请求,必须调用 send()方法
- 接收一个参数,即要作为请求主体发送的数据。
- 如果不需要通过请求主体发送 数据,则必须传入 null
- 在收到响应后,响应 的数据会自动填充 XHR对象的属性,相关的属性简介如下。
status:响应的 HTTP状态。
statusText:HTTP状态的说明。
responseText:作为响应主体被返回的文本。
responseXML:如果响应的内容类型是"text/xml"或"application/xml",
这个属性中将保存包含着响应数据的 XML DOM文档。
- 在接收到响应后,第一步是检查 status 属性,以确定响应已经成功返回。
- 可以检测 XHR对象的 readyState 属性,该属性表示请求 /响应过程的当前活动阶段。
0:未初始化。尚未调用 open()方法。
1:启动。已经调用 open()方法,但尚未调用 send()方法。
2:发送。已经调用 send()方法,但尚未接收到响应。
3:接收。已经接收到部分响应数据。
4:完成。已经接收到全部响应数据,而且已经可以在客户端使用了。
- 只要 readyState 属性的值由一个值变成另一个值,都会触发一次 readystatechange 事件
- 另外,在接收到响应之前还可以调用 abort()方法来取消异步请求,如xhr.abort();
- HTTP头部信息
- 默认情况下,在发送 XHR 请求的同时,还会发送下列头部信息。
- 使用 setRequestHeader()方法可以设置自定义的请求头部信息。
- 这个方法接受两个参数:
- 头部字段的名称
- 头部字段的值。
- 要成功发送请求头部信息,必须在调用 open()方法之后且调用 send()方法 之前调用这个方法
- 在没有自定义信息的情况 下,getAllResponseHeaders()方法通常会返回如下所示的多行文本内容
Date: Sun, 14 Nov 2004 18:04:03 GMT
Server: Apache/1.3.29 (Unix)
Vary: Accept
X-Powered-By: PHP/4.3.8
Connection: close
Content-Type: text/html; charset=iso-8859-1
//这种格式化的输出可以方便我们检查响应中所有头部字段的名称,而不必一个一个地检查某个字段 是否存在。
- GET请求
查询字符串中每个参数的名 称和值都必须使用 encodeURIComponent()进行编码,然后才能放到 URL 的末尾;
而且所有名-值对儿都必须由和号(&)分隔
- POST请求
- 通常用于向服务器发送应该被保存的数据
xhr.open("post", "postexample.php", true);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
var form = document.getElementById("user-info");
xhr.send(serialize(form));
XMLHttpRequest 2级
- FormData
- FormData 为序列化表单以及创建与表单格式相同的数据(用于通过 XHR传输)提供 了便利
//创建一个 FormData 对象
var data = new FormData();
data.append("name", "Nicholas");
//创建FormData 的实例
var data = new FormData(document.forms[0]);
//以将它直接传给 XHR的 send()方法
xhr.open("post","postexample.php", true);
var form = document.getElementById("user-info");
xhr.send(new FormData(form));
//使用 FormData 的方便之处体现在不必明确地在 XHR 对象上设置请求头部
- 超时设定
- timeout 属性,表示请求在等待响应多少毫秒之后就终止。
- 在给 timeout 设置一个数值后,如果在规定的时间内浏览器还没有接收到响应
- 那么就会触发 timeout 事 件,进而会调用 ontimeout 事件处理程序。
xhr.open("get", "timeout.php", true);
xhr.timeout = 1000; //将超时设置为 1 秒钟(仅适用于 IE8+)
xhr.ontimeout = function(){
alert("Request did not return in a second.");
};
xhr.send(null);
- overrideMimeType()方法
- 用于重写 XHR响应的 MIME 类型
- 返回响应的 MIME类型决定了 XHR对象如何处理它
- 调用 overrideMimeType()必须在 send()方法之前,才能保证重写响应的 MIME类型
进度事件
- load事件
- 只要浏览器接收到服务器的响应,不管其状态如何,都会触发 load 事件
- progress事件
- 在浏览器接收新数据期间周期性地触发
- 必须在调用 open()方法之前添加 onprogress 事件处理程序
跨源资源共享
- IE对CORS的实现
- 其他浏览器对CORS的实现
- Preflighted Requests
- 带凭据的请求
- 跨浏览器的CORS
其他跨域技术
- 图像Ping
- 图像 Ping 是与服务器进行简单、单向的跨域通信的一种方式。
- 请求的数据是通过查询字符串形式发送的,而响应可以是任意内容,但通常是像素图或 204响应。
- 图像 Ping常用于跟踪用户点击页面或动态广告曝光次数。
- 图像 Ping有两个主要的缺点,一是只 能发送 GET 请求,二是无法访问服务器的响应文本。
var img = new Image();
img.onload = img.onerror = function(){
alert("Done!");
};
img.src = "http://www.example.com/test?name=Nicholas";
- JSONP
- JSONP由两部分组成:回调函数和数据。
- 与图像 Ping 相比,它的优点 在于能够直接访问响应文本,支持在浏览器与服务器之间双向通信。
- 不过,JSONP也有两点不足。
- 首先,JSONP是从其他域中加载代码执行。
- 其次,要确定 JSONP请求是否失败并不容易。
- JSONP 是通过动态<script>元素来使用的,使用时可以为 src 属性指定一个跨域 URL
function handleResponse(response){
alert("You’re at IP address " + response.ip + ", which is in " +
response.city + ", " + response.region_name);
}
var script = document.createElement("script");
script.src = "http://freegeoip.net/json/?callback=handleResponse";
document.body.insertBefore(script, document.body.firstChild);
- Comet
- Comet 是对 Ajax 的进一步扩展,让服务器几乎能够实时地向客户端推送数据。
- 实现 Comet 的手段 主要有两个:长轮询和 HTTP流。
- 所有浏览器都支持长轮询,而只有部分浏览器原生支持 HTTP流。
- SSE (服务器发送事件)是一种实现 Comet 交互的浏览器 API,既支持长轮询,也支持 HTTP流。
- 服务器发送事件
- Web Sockets
- Web Sockets是一种与服务器进行全双工、双向通信的信道。
- 与其他方案不同,Web Sockets不使用 HTTP 协议,而使用一种自定义的协议。
- 这种协议专门为快速传输小数据设计。虽然要求使用不同的 Web 服务器,但却具有速度上的优势。
- SSE与Web Sockets
安全
为确保通过 XHR访问的 URL安全,通行的做法就是验证发送请求者是否有权限访问相应的资源。