首页 > 代码库 > javascript AJAX与Comet详解

javascript AJAX与Comet详解

 

 
  •  
  •  
  •  
  •  

 

博客专家福利       【限时活动】建专辑得大奖       专访荣浩:流程的永恒之道       当青春遇上互联网,能否点燃你的创业梦       推荐有礼--找出您心中的技术大牛
 

javascript AJAX与Comet详解

分类: javascript
XMLHttpRequest对象
在IE5中,XHR对象是通过MSXML库中的ActiveX对象实现的。在IE中可能会遇到三种不同版本的XHR对象,即MSXML2.XMLHttp、MSXML2.XMLHttp.3.0和MXSML.XMLHttp.6.0。IE7之后的版本和其他浏览器都会使用下面的函数来创建:
var xhr=new 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){
  //skip;
}   
   }
    }
return new ActiveXObject(arguments.callee.activeXString);
   }else{
     throw new Error("No XHR object available.");
   }
 
XHR的用法
在使用XHR对象时,要调用的第一方法时open(),它接收三个参数:要发送请求的类型,请求的URL和表示是否异步发送请求的布尔值。
xhr.open("get","example.php",false);
要发送特定的请求,要向下面一样调用send()方法:
xhr.open("get","example.php",false);
xhr.send(null);
XHR从服务器返回后,发生变化的属性,即保存服务器相应数据的属性为:
responseText:作为响应主体被返回的文本
responseXML:如果响应类型是"text/xml"和"application/xml",则保存着响应数据的XML DOM文档
status:响应的HTTP状态
statusText:HTTP状态的说明
在使用XHR之前必须指定onreadystatechange事件处理程序才能保证跨浏览器兼容性。
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.text",true);
xhr.send(null);
另外在接收到响应之前还可以调用abort()方法来取消异步请求。如下所示:
xhr.abort();
在终止请求之后,还应该对XHR对象进行解引用操作。由于内存原因,不建议重用XHR对象。
 
HTTP头部信息
XHR对象提供了操作请求头部和响应头部信息的方法。在默认情况下,在发送XHR请求同时,还会发送下列头部信息:
Accept:浏览器能够处理的内容类型
Accept-Charset:浏览器能够显示的字符集
Accept-Encoding:浏览器能够处理的压缩编码
Accept-Language:浏览器当前设置的语言
Connection:浏览器与服务器之间连接的类型
Cookie:当前页面设置的任何Cookie
Host:发送请求的页面所在的域
Referer:发送请求的页面的URI
User-Agent:浏览器的用户代理字符串
使用setRequestHeader()方法可以设置自定义的请求头部信息。这个方法接收两个参数:头部字段名和头部字段值。要成功发送请求头部信息,必须在调用open()方法之后且send()方法之前调用它。建议使用自定义的头部名称,而且浏览器有的支持有的不支持。
 
POST请求
使用post提交,要设置头部属性Content-type。如果不设置,会出现数据无法解码和获取等问题。
 
XMLHttpRequest 2级
并非所有的浏览器都完整的实现了XMLHttpRequest 2级的规范,但是所有的浏览器都实现了它部分的规范。
FormData
它是为序列化表单以及创建于表单格式相同的数据提供了遍历。使用方式参考下面的两个例子:
var data=http://www.mamicode.com/new FormData();
data.append("name","seacean2000");
 
var data=http://www.mamicode.com/new FormData(document.forms[0]);
它的方便之处在于不用明确的在XHR对象上设置请求头部。
 
超时设定
IE8+唯一支持的超时设定事件,XHR对象的ontimeout事件。XHR对象的timeout设定超时时间,单位是毫秒数。这些设定要方法open之后,send之前。
//open
xhr.timeout=1000;
xhr.ontimeout=function(){   };
//send
 
overrideMimeType()方法
用于重写XHR响应的MIME类型。它能强迫服务器返回的数据类型给些为本方法提供的类型。使用方法:
在open之后,send之前。
 
进度事件
有以下6个进度事件:
loadstart:在接收到响应数据的第一个字节时触发。
progress:在接收响应数据期间持续的触发
error:在请求发生错误时触发
abort:在因调用abort()方法而终止连接时触发
load:在接收到完整的响应数据时触发
loadend:在通信完成或者触发error,abort,load事件后触发。
现在所有的主流浏览器都支持load事件,前五个除了IE其他的都支持
 
load事件
并非所有的浏览器都为了这个事件实现了适当的事件对象。下面是使用示例:
xhr.onload=function(){
   if((xhr.status>=200&&xhr.status<300)||xhr.status==304){
   alert(xhr.responseText);
   }else{
   alert("Request was unsuccessful:"+xhr.status);   
   } 
}
放到open方法之前。
 
progress事件
Mozilla为XHR新添加的事件,这个事件会在浏览器接收数据期间周期性的触发。而onprogress事件处理程序会接收一个event对象,其target属性是XHR对象,但包含着三个额外属性:lengthComputable,position,tatalSize.其中lengthComputable表示进度信息是否可用的布尔值,position表示已经接收的字节数,totalSize表示根据Content-Length响应头部确定的预期字节数。有了这些我们就可以为用户创建一个进度指示器。
xhr.onprogress=function(event){
var divStatus=document.getElementById("status");
if(event.lengthComputable){
 divStatus.innerHTML="Received "+event.position+" of "+event.totalSize+" bytes";
}
};
要放到open之前才可以。
 
跨源资源共享
通过XHR实现Ajax通信的一个主要限制,来源于跨域安全策略。在默认情况下,Ajax只能访问与包含它的页面位于同一个域中的资源。但是有时也需要一些跨域的请求。为了解决这个问题,现在的浏览器采用CORS(Cross-Origin Resource Sharing,跨域资源共享)策略来实现。CORS是W3C的一个工作草案,定义了必须访问跨源资源时浏览器与服务器之间如何进行沟通。这个策略的基本思想是使用自定义的HTTP头部让浏览器与服务器进行沟通,从而决定请求或响应的成功和失败。注意请求和响应都不包含cookie信息。
 
IE对CORS的实现
IE8中引入了XDR(XDomainRequest)类型,这个对象与XHR类似,但是能实现安全可靠的跨域通信。XDR对象的安全机制部分实现了W3C的CORS规范。以下是XDR与XHR的不同之处:
cookie不会随请求发送,也不会随响应返回
只能设置请求头部信息中的Content-Type字段
不能访问响应头部信息
只支持GET和POST请求
XDR对象使用方法:创建一个实例,调用open方法,调用send方法。open方法只接受两个参数:请求的类型和URL。所有XDR的请求都是异步的。请求返回后会触发load事件,响应数据保存在responseText属性中。
var xdr=new XDomainRequest();
xdr.onload=function(){
  alert(xdr.responseText);
};
xdr.open("get","http://www.somewhere-else.com/page/");
xdr.send(null);
在跨域请求上唯一可以获得响应的信息就是错误本身,因此确定响应失败的方式就是使用onerror事件。要放到open之前使用。
xdr.onerror=function(){
   alert("an error occurred!");
}
在请求返回之前,可以调用取消命令abort()方法:
xdr.abort();//终止请求
与XHR一样,XDR对象也支持timeout属性以及ontimeout事件处理程序。
xdr.timeout=1000;
xdr.ontimeout=function(){
alert("late!")
}
将这些处理程序添加到open之前才可以哦。
为了支持post请求,XDR对象提供了contentType属性,用来表示发送数据的格式:在open之后,send之前设置
xdr.contentType="application/x-www-form-urlencoded";
 
其他浏览器对CORS的实现
其他的浏览器都通过XMLHttpRequest对象实现了对CORS的原生支持。但是在跨域请求的时候有以下的限制:
不能使用setRequestHeader()设置自定义头部。
不能接受和发送cookie
调用getAllResponseHeaders()方法总会返回空字符串。
无论是同源请求还是跨域请求,对于本地资源最好使用相对URL,在访问远程资源时再使用绝对URL。
 
Preflighted Requests
透明服务器验证机制,支持开发人员使用自定义的头部,get和post之外的方法,以及不同类型的主题内容。这种请求使用OPTIONS方法,发送下列头部:
Origin:与简单的请求相同
Access-Control-Request-Method:请求自身使用的方法
Access-Control-Request-Headers:(可选)自定义头部信息,多喝头部逗号分隔。
发送请求之后,服务器决定是否允许这种类型的请求。服务器通过响应发送如下的头部与浏览器进行沟通:
Access-Control-Allow-Origin:与简单的请求相同
Access-Control-Allow-Methods:允许的方法,多个方法以逗号分隔
Access-Control-Allow-Headers:允许的头部,多个头部以逗号分隔
Access-Control-Max-Age:应该将这个Preflight请求缓存多长时间(以秒表示)
 
带凭据的请求
通过将withCredentials属性设置为true,可以指定特定的请求应该发送凭据。如果服务器接收带凭据的请求,会用下面的HTTP头部响应
Access-Control-Allow-Credentials:true
 
跨浏览器的CORS
function createCORSRequest(method,url){
   var xhr=new XMLHttpRequest();
   if("withCredentials" in xhr){
   xhr.open(method,url,true);   
    }else if(typeof XDomainRequest!="undefined"){
    xhr=new XDomainRequest();
xhr.open(method,url);
    }else{
   xhr=null;
    }
return xhr;
}
var request=createCORSRequest("get","http://somewhere-else.com/page/");
if(request){
   request.onload=function(){
      //request.responseText
   };
   request.send();   
}
 
其他的跨域技术
图像Ping技术
根据一个网页可以从任何网页中加载图像而不用担心使用跨域的原理,我们可以动态的创建图像,使用他们的onload和onerror事件处理程序来确定是否收到响应。
动态的创建图像经常用于图像Ping。图像Ping是与服务器进行简单的单向的跨域通信的一种方式。请求的数据通过查询字符串形式发送的,而响动可以是任意内容,但通常是像素图或者204响应。通过图像Ping,浏览器得不到任何具体的数据,但是通过侦听load和error事件,它能知道是什么时候接受的。
var img=new Image();
img.onload=img.onerror=function(){
  alert("Done");
};
img.src="http://ww.example.com/test?name=seacean";
图像Ping最常用于跟踪用户点击页面或动态广告曝光次数。它有两个主要的缺点:只能发送get请求,无法访问服务器的响应文本。因此,图像Ping只能用于浏览器与服务器间的单向通信。
 
JSONP
JSONP是JSON with padding的简写,是应用json的一种新方法,在后来的Web服务中非常流行。JSONP由两部分组成:回调函数和数据。回调函数式当响应到来时应该在页面中调用的函数,回调函数的名字一般是在请求中指定的。数据就是传入回调函数的json数据。下面是以个JSONP的例子:
http://freegeoip.net/json/?callback=handleResponse
JSONP是通过动态的<script>元素来使用的,使用时可以为src属性指定一个跨域URL。这里的<script>元素有能力不受限制的同其他域加载资源。因为JSONP是有效地javascript代码,所以在请求完成后,即在JSONP响应加载到页面后会立即执行。
function handlerResponse(response){
  alert("You‘re at IP address "+response.ip+", where is in "+response.city+", "+response.region_name);
}
var script=document.createElement("script");
script.src="http://freegeoip.net/json/?callback=handlerResponse";
document.body.insertBefore(script,document.body.firstChild);
JSONP的优势在于简单易用,直接访问响应文本,支持浏览器与服务器之间的双向通信。JSONP的不足之处:不能确定加载的域是否安全,要确定请求失败并不容易。为了避免这些,开发人员的现行方案是用指定时间内是否接收到了响应来判断。
 
Comet
这是一种服务器向页面推送数据的技术。Comet能够让信息近乎实时的被推送到页面上,非常适合处理体育比赛和股票报价。有两种实现Comet的方式:长轮询和流。长轮询是传统轮询的一个翻版,即浏览器定时向服务器发送请求,看看有没有数据更新。长轮询把传统轮询颠倒了一下,页面发送一个到服务器的请求,然后服务器一直保持连接打开,知道有数据可发送。发送完数据后,浏览器关闭连接,随即又发起一个到服务器的新请求。这个过程在页面打开期间一直不断持续。第二种流行的Comet方式是HTTP流。流在页面的整个生命周期中只使用一个HTTP连接。具体来说就是浏览器向服务器发送一个请求,然后服务器保持连接打开,然后周期性的向浏览器发送数据。下面这段php脚本就是采用流实现的服务器中的常见方式:
$i=0;
while(true){
echo "Number is $i";//输出数据然后刷新缓存
flush();
sleep(10);//停止几秒
$i++;
}
这段代码是实现HTTP流的关键。
下面这段代码是XHR对象实现HTTP流的典型代码:
function createStreamingClient(url,progress,finished){
var xhr=new XMLHttpRequest(),received=0;
 
xhr.open("get",url,true);
xhr.onreadystatechange=function(){
  var result;
  if(xhr.readyState==3){
  result=xhr.responseText.substring(received);
  received+=result.length;
  progress(result);
  }else if(xhr.readyState==4){
  finished(xhr.responseText);
  }
};
xhr.send(null);
return xhr;
}
var client=createStreamingCilent("streaming.php",function(data){
  alert("Received:"+data);
  },function(data){
  alert("Done!");
  });
这个createStreamingCilent函数接收三个参数:要连接的URL,在接收到数据时调用的函数以及关闭连接时调用的函数。
 
服务器发送事件
SSE(Server-Sent Events,服务器发送事件)是围绕只读Comet交互推出的API或者模式。SSE API用于创建到服务器的单向连接,服务器通过这个连接可以发送任意数量的数据。服务器响应的MIME类型必须是text/event-stream,而且是浏览器中的Javascript API能解析的格式输出。SSE支持短轮询,长轮询和HTTP流,而且能够在断开连接时自动确定何时重新连接。
SSE API
SSE是为javascript api与其他传递消息的javascript api很相似。要预定新的事件流,要创建新的EventSource对象,并传入一个入口点:
var source=new EventSource("myevents.php");
注意:要传入的URL必须与创建对象的页面同源。EventSource的实例有一个readyState属性,值为0表示正连接到服务器,值为1表示打开了连接,值为2表示关闭连接。另外还有三个事件:
open:在建立连接时触发
message:在从服务器接收到新事件时触发
error:在无法建立连接时触发
服务器返回的数据以字符串的格式保存在event.data中。如果想强制立即断开并且不再重新连接,可以调用close()方法。
事件流
多段数据发送时,要以换行符进行分隔不同段的数据。而且还可以在每段数据的前面或者后面附加ID,以便多段数据的拼接。在设置了ID之后,EventSource对象会跟踪上一次触发的事件。如果连接断开,会向服务器发送一个包含名为Last-Event-ID的特殊HTTP头部请求,以便服务器知道下次触发那个事件。在多次连接的事件流中,这种机制保证了浏览器能够以正确的顺序接收到连接的数据段。
 
Web Sockets
在js中web sockets使用了自定义的协议。未加密的协议是ws://;加密的协议是wss://.目前支持它的的浏览器有FireFox6+,safari5+,Chrome,IOS4+版safari。
创建web sockets的例子:
var sockets=new WebSockets("ws://www.example.com/server.php");
注意,必须给WebSockets构造函数传入绝对的URL。同源策略对它不适用。能否与特定的域通信完全取决于服务器。
sockets.close();   //关闭
sockets.send("Hello word");//可以发送字符串,json格式的字符串
sockets的事件有onmessage:服务器向客户端发送消息,sockets会触发;onopen:成功建立连接时触发;onerror:在发生错误时触发,连接时不能持续;onclose:在连接关闭时触发。在close事件中的event对象有三个额外的属性:wasClean,code,reason.第一个参数表示连接是否明确的关闭,布尔值。第二个是服务器返回的数值状态码,而reason是一个字符串,包含服务器返回的信息。
 
Web Sockets协议比同于HTTP,现有的服务器不能用Web Sockets通信,HTTP可以满足要求。如果只需要向服务器请求数据,那么SSE比较容易,要是双向的通信Web Sockets更好一些。在不能使用Web Sockets的情况下,组合XHR+SSE也能实现双向通信。
 
在AJAX安全方面,下列措施是得力的:
要求以SSL连接来访问可以通过XHR请求的资源
要求每一次请求都要附带经过相应算法计算得到的验证码
 
 
 
 
 
 
主题推荐
javascriptajaxcometweb服务开发人员
猜你在找
DWR高级主题之反向Ajax(Comet模式--DWR2.X)
Ajax、Comet、HTML 5 Web Sockets技术比较分析
关于用ajax长链接轮询方式实现comet时,其他ajax请求被阻塞的问题
javascript基础知识复习4-JS中的跨域解决方案和Comet
Comet 与传统的 Ajax 轮询相比性能方面是否占优?哪些大型网站在哪些方面用到 Comet ?
JavaScript学习 jquery学习11 ajax开发
JavaScript Ajax详解
JavaScript、JQuery、Ajax区别与联系
非ajax提交页面不跳转,java调用javascript详解
javascript中的AJAX
查看评论

  暂无评论

 
 
发表评论
  • 用 户 名:
  • u012162858
  • 评论内容:
  • 插入代码
      
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
 
快速回复
核心技术类目
全部主题 Hadoop AWS 移动游戏 Java Android iOS Swift 智能硬件 Docker OpenStack VPN Spark ERP IE10Eclipse CRM JavaScript 数据库 Ubuntu NFC WAP jQuery BI HTML5 Spring Apache .NET API HTML SDK IISFedora XML LBS Unity Splashtop UML components Windows Mobile Rails QEMU KDE Cassandra CloudStack FTCcoremail OPhone CouchBase 云计算 iOS6 Rackspace Web App SpringSide Maemo Compuware 大数据 aptech PerlTornado Ruby Hibernate ThinkPHP HBase Pure Solr Angular Cloud Foundry Redis Scala Django Bootstrap
 
    个人资料
 
神赐予我钱途吧
 
    • 访问:31459次
    • 积分:1135分
    • 排名:第14415名
    • 原创:83篇
    • 转载:16篇
    • 译文:3篇
    • 评论:3条
    文章搜索
    文章分类
  • java(28)
  • javascript(35)
  • SQL(3)
  • SVG(3)
  • structs2(4)
  • 读书笔记(37)
  • 我的程序员之道(7)
  • UML基础(12)
    文章存档
  • 2014年09月(2)
  • 2014年06月(1)
  • 2014年05月(2)
  • 2014年01月(3)
  • 2013年11月(1)
展开
    阅读排行
  • UML各种视图的简介(2299)
  • 一个java状态机样例的代码(2107)
  • structs2 工作原理(1985)
  • SVG animation动画(1829)
  • javascript DOM详解之DOM2与DOM3(957)
  • java Arrays.sort的使用问题(587)
  • javascript 脚本化的HTTP----ajax的基石(561)
  • javascript SVG的动画,脚本,事件(544)
  • springmvc 快速突破(三)---一个控制器多个方法问题(530)
  • javascript JSON详解(476)
    评论排行
  • UML各种视图的简介(2)
  • javascript DOM扩展(1)
  • java 打印三角形,菱形的方法(0)
  • 我逛贴吧后的想法(0)
  • 代理模式的个人分析(0)
  • 生病了,坐在电脑前发呆时候胡思乱想(0)
  • SVG animation动画(0)
  • java 集合(0)
  • java 数据库编程(0)
  • UML基础以及必要性(0)
    推荐文章
    最新评论
  • UML各种视图的简介

    神赐予我钱途吧: 在看之前一定要确信它包含你想要的东西,迫切程度与枯燥程度成反比。

  • UML各种视图的简介

    changshenglugu: 看不进去……

  • javascript DOM扩展

    神赐予我钱途吧: 元素的遍历问题Element Traversal规范为了解决一些浏览器兼容问题,Element Tr...

 
 
公司简介|招贤纳士|广告服务|银行汇款帐号|联系方式|版权声明|法律顾问|问题报告|合作伙伴|论坛反馈
网站客服 杂志客服 微博客服 webmaster@csdn.net 400-600-2320
京 ICP 证 070598 号
北京创新乐知信息技术有限公司 版权所有
江苏乐知网络技术有限公司 提供商务支持
Copyright © 1999-2014, CSDN.NET, All Rights Reserved GongshangLogo
 

javascript AJAX与Comet详解