学习第十二天(2019-11-25)

第二十一章 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 服务器,但却具有速度上的优势。 

猜你喜欢

转载自www.cnblogs.com/xiaoxb17/p/11930808.html
今日推荐