第二十一章 Ajax与Comet
Ajax是无需刷新页面就能够从服务器取得数据的一种方法,Ajax技术的核心是XMLHttpRequest对象(简称 XHR)。
一、XMLHttpRequest对象
1、由于IE与其他浏览器实现的方式不一样,所以只能用下面方法实现跨浏览器创建XMLHttpRequest对象;
1 function createXHR(){ 2 if (typeof XMLHttpRequest != "undefined"){ 3 return new XMLHttpRequest(); 4 }else if(typeof ActiveXObject != "undefined"){ 5 if(typeof arguments.callee.activeXString != "string"){ 6 var versions = [ "MSXML2.XMLHttp.6.0", "MSXML2.XMLHttp.3.0","MSXML2.XMLHttp"], 7 i, len; 8 for (i=0,len=versions.length; i < len; i++){ 9 try { 10 new ActiveXObject(versions[i]); 11 arguments.callee.activeXString = versions[i]; 12 break; 13 }catch(ex){ } //跳过 14 } 15 } 16 return new ActiveXObject(arguments.callee.activeXString); 17 } else { 18 throw new Error("No XHR object available."); 19 } 20 } 21 22 //创建XHR对象 23 var xhr = createXHR();
2、XHR的用法
主要有三个方法:
open() 方法接收 3 个参数:要发送的请求的类型( "get" 、 "post" 等)、请求的 URL 和表示是否异步发送请求的布尔值。调用 open() 方法并不会真正发送请求,而只是启动 一个请求以备发送。
send()方法接收一个参数:要作为请求主体发送的数据。如果不需要通过请求主体发送数据,则必须传入 null。
abort() 方法用于取消异步请求。
3、每个HTTP请求和响应都会带有相应的头部信息,XHR 对象也提供了操作头部(即请求头部和响应头部)信息的方法; GET请求:最常用于向服务器查询某些信息。 POST请求:通常用于向服务器发送应该被保存的数据。
二、XMLHttpRequest2级
1、FormData:FormData为序列化表单以及创建与表单格式相同的数据(用于通过XHR传输)提供了便利:
使用方法:
1 var data = new FormData(); 2 data.append("name", "Nicholas"); 3 4 //或者传入表单元素 5 var data = new FormData(document.forms[0]);
使用FormData的方便之处体现在不必明确地在XHR对象上设置请求头部。XHR对象能够识别传入的数据类型是FormData的实例,并配置适当的头部信息。
2、超时设定
IE8为XHR对象添加了一个timeout 属性,表示请求在等待响应多少毫秒之后就终止。在给timeout设置一个数值后,如果在规定的时间内浏览器还没有接收到响应,那么就会触发timeout事 件,进而会调用ontimeout 事件处理程序。
3、overrideMimeType()方法:用于重写XHR响应的MIME类型
1 var xhr = new XMLHttpRequest(); 2 xhr.open("get", "text.php", true); 3 xhr.overrideMimeType("text/xml" ); 4 //xhr.overrideMimeType(text/plain); 5 xhr.send(null);
三、进度事件:
Progress Events规范是W3C的一个工作草案,定义了与客户端服务器通信有关的事件。这些事件 早其实只针对 XHR操作,但目前也被其他 API借鉴。有以下 6个进度事件:
loadstart、progress、error、abort、load、loadend、loadstart;
1、load事件
只要浏览器接收到服务器的响应,不管其状态如何,都会触发load事件。而这意味着你必须要检查 status 属性,才能确定数据是否真的已经可用了,如下:
1 var xhr = createXHR(); 2 xhr.onload = function(){ 3 if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){ 4 alert(xhr.responseText); 5 } else { 6 alert("Request was unsuccessful: " + xhr.status); 7 } 8 }; 9 xhr.open("get", "altevents.php", true); 10 xhr.send(null);
2、progress事件:这个事件会在浏览器接收新数据期间周期性地触发,onprogress事件处理程序会接收到一个event对象,其target属性是XHR对象,但包含着三个额外的属性:lengthComputable、position 和 totalSize。其中,lengthComputable 是一个表示进度信息是否可用的布尔值,position 表示已经接收的字节数,totalSize 表示根据 Content-Length 响应头部确定的预期字节数。
下面展示了为用户创建进度指示器的一个示例:
1 var xhr = createXHR(); 2 xhr.onload = function(event){ 3 if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){ 4 alert(xhr.responseText); 5 } else { 6 alert("Request was unsuccessful: " + xhr.status); 7 } 8 }; 9 xhr.onprogress = function(event){ 10 var divStatus = document.getElementById("status"); 11 if (event.lengthComputable){ 12 divStatus.innerHTML = "Received " + event.position + " of " + 13 event.totalSize +" bytes"; 14 } 15 }; 16 xhr.open("get", "altevents.php", true); 17 xhr.send(null);
四、跨资源共享
通过XHR实现Ajax通信的一个主要限制,来源于跨域安全策略。默认情况下,XHR对象只能访问与包含它的页面位于同一个域中的资源。CORS(跨源资源共享)是 W3C的一个工作草案,定义了在必须访问跨源资源时,浏览器与服务器应该如何沟通。CORS背后的基本思想,就是使用自定义的 HTTP头部让浏览器与服务器进行沟通,从而决定请求或响应是应该成功,还是应该失败。
1、IE对CORS的实现
微软在 IE8中引入了 XDR(XDomainRequest)类型。这个对象与 XHR类似,但能实现安全可靠 的跨域通信。XDR对象的安全机制部分实现了 W3C的 CORS规范。
2、其他浏览器对CORS的实现
Firefox 3.5+、Safari 4+、Chrome、iOS版Safari和Android平台中的WebKit都通过 XMLHttpRequest 对象实现了对CORS的原生支持。
3、跨浏览器的CORS
即使浏览器对CORS的支持程度并不多一样,但所有浏览器都支持简单的(非Preflight和不带凭据的)请求,因此检测XHR是否支持CORS的最简单的方式,就是检查是否存在withCredentials属性。再结合XDomainRequest对象是否存在,就可以兼顾所有浏览器了。
代码:
1 function createCORSRequest(method, url){ 2 var xhr = new XMLHttpRequest(); 3 if ("withCredentials" in xhr){ 4 xhr.open(method, url, true); 5 } else if (typeof XDomainRequest != "undefined"){ 6 xhr = new XDomainRequest(); 7 xhr.open(method, url); 8 } else { 9 xhr = null; 10 } 11 return xhr; 12 } 13 14 var request = createCORSRequest("get", "http://www.somewhere-else.com/xdr.php"); 15 if (request){ 16 request.onload = function(){ 17 //对request.responseText进行处理 18 }; 19 request.send(); 20 }
五、其他跨域技术
1、图像Ping:请求的数据是通过查询字符串形式发送的,而响应可以是任意内容,但通常是像素图或 204 响应。通过图像 Ping,浏览器得不到任何具体的数据,但通过侦听 load 和 error 事件,它能知道响应是什么时候接收到的。图像 Ping 最常用于跟踪用户点击页面或动态广告曝光次数。图像 Ping 有两个主要的缺点,一是只能发送GET 请求,二是无法访问服务器的响应文本。
2、JSONP:JSONP 是被包含在函数调用中的 JSON。JSONP 由两部分组成——回调函数和数据。回调函数是当响应到来时应该在页面中调用的函数,回调函数的名字一般是在请求中指定的。而数据就是传入回调函数中的JSON数据。与图像 Ping 相比,它的优点在于能够直接访问响应文本,支持在浏览器与服务器之间双向通信。不过,JSONP 也有两点不足,首先,JSONP 是从其他域中加载代码执行,其次,要确定 JSONP 请求是否失败并不容易。
3、Comet
Comet:服务器推送。刚好与Ajax相反,Ajax是一种从页面向服务器请求数据的技术,而Comet则是一种服务器向页面推送数据的技术。Comet能够让信息近乎实时地被推送到页面上,非常适合处理体育比赛的分数和股票涨价。 有两种实现Comet的方式:长轮询和流。
1、长轮询是传统轮询(也称为短轮询)的一个翻版,即浏览器定时向服务器发送请求,看有没有更新的数据。
2、HTTP流就是浏览器向服务器发送一个请求,而服务器保持连接打开,然后周期性地向浏览器发送数据。
使用XHR对象实现HTTP流的典型代码如下所示:
1 function createStreamingClient(url, progress, finished){ 2 3 var xhr = new XMLHttpRequest(), 4 received = 0; 5 6 xhr.open("get", url, true); 7 xhr.onreadystatechange = function(){ 8 var result; 9 10 if (xhr.readyState == 3){ 11 12 //只取得最新数据并调整计数器 13 result = xhr.responseText.substring(received); 14 received += result.length; 15 16 //调用progress回调函数 17 progress(result); 18 19 } else if (xhr.readyState == 4){ 20 finished(xhr.responseText); 21 } 22 }; 23 xhr.send(null); 24 return xhr; 25 } 26 27 var client = createStreamingClient("streaming.php", function(data){ 28 alert("Received: " + data); 29 }, function(data){ 30 alert("Done!"); 31 });
4、服务器发送事件(SSE):是围绕只读 Comet 交互推出的 API 或者模式。SSE 支持短轮询、长轮询和 HTTP 流,而且能在断开连接时自动确定何时重新连接。
SSE API:用于创建到服务器的单向连接,服务器通过这个连接可以发送任意数量的数据。
事件流:服务器事件会通过一个持久的 HTTP 响应发送,这个响应的 MIME 类型为 text/event-stream 。响应的格式是纯文本,最简单的情况是每个数据项都带有前缀 data:。
5、Web Sockets:Web Sockets的目标是在一个单独的持久连接上提供全双工、双向通信。在 JavaScript 中创建了 Web Socket 之后,会有一个 HTTP 请求发送到浏览器以发起连接。在取得服务器响应后,建立的连接会使用 HTTP 升级从HTTP 协议交换为 Web Socket 协议。这种协议专门为快速传输小数据设计。虽然要求使用不同的Web 服务器,但却具有速度上的优势。
原文:https://www.cnblogs.com/xiaoxb17/p/11930808.html