JavaScript 高级程序设计(第21 Ajax 与 Comet)

第21 Ajax 与 Comet

1. XMLHttpRequest对象

创建XHR对象

function createXHR(){
        if (typeof XMLHttpRequest != "undefined"){
            return new XMLHttpRequest();
        } else if (typeof ActiveXObject != "undefined"){
           if (typeof arguments.callee.activeXString != "string"){
               var versions = [ "MSXML2.XMLHttp.6.0", "MSXML2.XMLHttp.3.0","MSXML2.XMLHttp"],i, len;
           for (i=0,len=versions.length; i < len; i++){
               try {
                   new ActiveXObject(versions[i]);
                         arguments.callee.activeXString = versions[i];
                   break;
                } catch (ex){
                        //跳过 
                }
            }
       }
       return new ActiveXObject(arguments.callee.activeXString);
        } else {
        throw new Error("No XHR object available.");
    }
}

var xhr = createXHR();

(1) XHR的用法

open()方法:

接受 3 个参数:要发送的请求的类型("get"、"post"等)、请求的 URL 和表示是否异步发送请求的布尔值。
xhr.open("get", "example.php", false);

send()方法:

发送特定的请求,send()方法接收一个参数,即要作为请求主体发送的数据。如果不需要通过请求主体发送 数据,则必须传入 null,因为这个参数对有些浏览器来说是必需的。调用 send()之后,请求就会被分 派到服务器。
xhr.open("get", "example.txt", false);
xhr.send(null);

XHR 对象的属性:

在收到响应后,响应 的数据会自动填充 XHR 对象的属性

  1. responseText:作为响应主体被返回的文本。
  2. responseXML:如果响应的内容类型是"text/xml"或"application/xml",这个属性中将保
    存包含着响应数据的 XML DOM 文档。
  3. status:响应的 HTTP 状态。
  4. statusText:HTTP 状态的说明。
  5. readyState: 表示请求 /响应过程的当前活动阶段。
  • 0:未初始化。尚未调用 open()方法。
  • 1:启动。已经调用 open()方法,但尚未调用 send()方法。
  • 2:发送。已经调用 send()方法,但尚未接收到响应。
  • 3:接收。已经接收到部分响应数据。
  • 4:完成。已经接收到全部响应数据,而且已经可以在客户端使用了。
    readyState 属性的值由一个值变成另一个值,都会触发一次 readystatechange 事件。
var xhr = createXHR();
    xhr.onreadystatechange = function(){
        if (xhr.readyState == 4){
            if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){
             alert(xhr.responseText);
        } else {
             alert("Request was unsuccessful: " + xhr.status);
        }
} };
xhr.open("get", "example.txt", true);
xhr.send(null);
abort()方法:

调用这个方法后,XHR 对象会停止触发事件,而且也不再允许访问任何与响应有关的对象属性。在 终止请求之后,还应该对 XHR 对象进行解引用操作。由于内存原因,不建议重用 XHR 对象。

(2) HTTP头部信息

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

设置自定义的请求头部信息。
这个方法接受两个参数:头部字段 的名称和头部字段的值。要成功发送请求头部信息,必须在调用 open()方法之后且调用 send()方法 之前调用 setRequestHeader()

getResponseHeader()方法:

传入头部字段名称,可以取得相应的响应头部信息。

getAllResponseHeaders()方法

可以取得一个包含所有头部信息的长字符串。

(3) GET请求

可以将查询字符串参数追加 到 URL 的末尾,以便将信息发送给服务器。对 XHR 而言,位于传入 open()方法的 URL 末尾的查询字 符串必须经过正确的编码才行。

xhr.open("get", "example.php?name1=value1&name2=value2", true);

function addURLParam(url, name, value) {
        url += (url.indexOf("?") == -1 ? "?" : "&");
        url += encodeURIComponent(name) + "=" + encodeURIComponent(value);
        return url;
}
var url = "example.php";
//添加参数
url = addURLParam(url, "name", "Nicholas");
url = addURLParam(url, "book", "Professional JavaScript");
//初始化请求
xhr.open("get", url, false);

(4) POST请求

用于向服务器发送应该被保存的数据,向 send()方法中传入某些数据。

2. XMLHttpRequest 2 级

(1) FormData

FormData 为序列化表单以及创建与表单格式相同的数据(用于通过 XHR 传输)提供 了便利。

var data = new FormData();
data.append("name", "Nicholas");

append()方法接收两个参数:键和值,分别对应表单字段的名字和字段中包含的值。可以像 这样添加任意多个键值对儿。而通过向 FormData 构造函数中传入表单元素,也可以用表单元素的数据 预先向其中填入键值对儿:

var data = new FormData(document.forms[0]);

(2) 超时设定

XHR 对象添加了一个timeout 属性,表示请求在等待响应多少毫秒之后就终止。在给 timeout 设置一个数值后,如果在规定的时间内浏览器还没有接收到响应,那么就会触发 timeout 事 件,进而会调用 ontimeout 事件处理程序。

(3) overrideMimeType()方法

用于重写 XHR 响应的 MIME 类型。

3. 进度操作

6 个进度事件:

(1) loadstart:在接收到响应数据的第一个字节时触发。
(2) progress:在接收响应期间持续不断地触发。
(3) error:在请求发生错误时触发。
(4) abort:在因为调用 abort()方法而终止连接时触发。
(5) load:在接收到完整的响应数据时触发。
(6) loadend:在通信完成或者触发 error、abort 或 load 事件后触发。

(1) load事件

响应接收完毕后将触发 load 事件,因此也就没有必 要去检查 readyState 属性了。而 onload 事件处理程序会接收到一个 event 对象,其target 属性就指向 XHR 对象实例,因而可以访问到 XHR 对象的所有方法和属性。然而,并非所有浏览器都为这个事件实现了适当的事件对象。

(2)progress 事件

onprogress 事件处理程序会接收到一个 event 对象,其 target 属性是 XHR 对象,但 包含着三个额外的属性:lengthComputable、position 和 totalSize。其中,lengthComputable 是一个表示进度信息是否可用的布尔值,position 表示已经接收的字节数,totalSize 表示根据 Content-Length 响应头部确定的预期字节数。

4. 跨源资源共享

CORS(Cross-Origin Resource Sharing,跨源资源共享)

CORS 背后的基本思想,就是使用自定义的 HTTP 头部 让浏览器与服务器进行沟通,从而决定请求或响应是应该成功,还是应该失败。

比如一个简单的使用 GET 或 POST 发送的请求,它没有自定义的头部,而主体内容是 text/plain。在 发送该请求时,需要给它附加一个额外的 Origin 头部,其中包含请求页面的源信息(协议、域名和端 口),以便服务器根据这个头部信息来决定是否给予响应。
Origin: http://www.nczonline.net

如果服务器认为这个请求可以接受,就在Access-Control-Allow-Origin 头部中回发相同的源信息(如果是公共资源,可以回发"*")。
Access-Control-Allow-Origin: http://www.nczonline.net

如果没有这个头部,或者有这个头部但源信息不匹配,浏览器就会驳回请求。正常情况下,浏览器 会处理请求。注意,请求和响应都不包含 cookie 信息。

(1) IE对CORS的实现

XDR(XDomainRequest)类型。这个对象与 XHR 类似,但能实现安全可靠的跨域通信。

XDR 与 XHR 的一些不同之处:

  1. cookie 不会随请求发送,也不会随响应返回。
  2. 只能设置请求头部信息中的 Content-Type 字段。
  3. 不能访问响应头部信息。
  4. 只支持GET和POST请求。
  5. XDR 对象的 open()方法只接收两个 参数:请求的类型和 URL。
  6. 请求返回之后,会触发 load 事件, 响应的数据也会保存在 responseText 属性中
  7. 在接收到响应后,你只能访问响应的原始文本;没有办法确定响应的状态代码。

(2) 其他浏览器对CORS的实现

要请求位于另一个域中的资源,使用标准的 XHR 对象并在 open()方法中传入绝对 URL 即可。
跨域 XHR 对象限制:

  1. 不能使用 setRequestHeader()设置自定义头部。
  2. 不能发送和接收 cookie。
  3. 调用 getAllResponseHeaders()方法总会返回空字符串。

(3) Preflighted Reqeusts

CORS 通过一种叫做 Preflighted Requests 的透明服务器验证机制支持开发人员使用自定义的头部、 GET 或 POST 之外的方法,以及不同类型的主体内容。在使用下列高级选项来发送请求时,就会向服务 器发送一个 Preflight 请求。这种请求使用 OPTIONS 方法,发送下列头部。

  1. Origin:与简单的请求相同。
  2. Access-Control-Request-Method:请求自身使用的方法。
  3. Access-Control-Request-Headers:(可选)自定义的头部信息,多个头部以逗号分隔。
Origin: http://www.nczonline.net
Access-Control-Request-Method: POST
Access-Control-Request-Headers: NCZ

发送这个请求后,服务器可以决定是否允许这种类型的请求。服务器通过在响应中发送如下头部与 浏览器进行沟通。

  1. Access-Control-Allow-Origin:与简单的请求相同。
  2. Access-Control-Allow-Methods:允许的方法,多个方法以逗号分隔。
  3. Access-Control-Allow-Headers:允许的头部,多个头部以逗号分隔。
  4. Access-Control-Max-Age:应该将这个 Preflight 请求缓存多长时间(以秒表示)。
Access-Control-Allow-Origin: http://www.nczonline.net
Access-Control-Allow-Methods: POST, GET
Access-Control-Allow-Headers: NCZ
Access-Control-Max-Age: 172800016

(4) 带凭据的请求

默认情况下,跨源请求不提供凭据(cookie、HTTP 认证及客户端 SSL 证明等)。通过将 withCredentials 属性设置为 true,可以指定某个请求应该发送凭据。如果服务器接受带凭据的请 求,会用下面的 HTTP 头部来响应。
Access-Control-Allow-Credentials: true

5. 其他跨域技术

(1) 图像Ping

图像 Ping 是与服务器进行简单、单向的跨域通信的一种方式。 请求的数据是通过查询字符串形式发送的,而响应可以是任意内容,但通常是像素图或 204 响应。通过 图像 Ping,浏览器得不到任何具体的数据,但通过侦听 load 和 error 事件,它能知道响应是什么时 候接收到的。

(2) JSONP

JSONP 是 JSON with padding(填充式 JSON 或参数式 JSON)的简写,被包含在函数调用中的 JSON。
callback({ "name": "Nicholas" });

JSONP 由两部分组成:回调函数和数据。回调函数是当响应到来时应该在页面中调用的函数。回调 函数的名字一般是在请求中指定的。而数据就是传入回调函数中的 JSON 数据。

JSONP 是通过动态

你可能感兴趣的:(JavaScript 高级程序设计(第21 Ajax 与 Comet))