Ajax,是Asynchronous JavaScript + XML的简写,这一技术能向服务器请求额外的技术而无需卸载页面,会带给用户更好的体验。Ajax的核心是XMLHttpRequest对象。为了防止XSS(跨站点脚本)、CSRF(跨站点请求伪造)等攻击,Ajax有着同源策略的限制;解决跨域的方式有CORS(跨源资源共享)、图像Ping和JSONP。
Comet是对Ajax的扩展,让服务器向浏览器推送数据,有长轮询和HTTP流两种方式实现。
webSocket是一种使用自定义的协议,与服务器进行全双工、双向通信的方式。
一、XMLHttpRequest对象
1、创建
IE7+,firefox,Opera,Chrome和Safari都支持原生的XHR对象,如果要支持IE早期的版本,需要通过MSXML库中的一个ActiveX对象来实现,这个对象又存在三种不同的版本,因此,如果要兼容所有浏览器,创建XHR对象的函数应该这样定义:
function createXHR(){ // 先检测原生XMLHttpRequest是否存在 if(typeof XMLHttpRequest != 'undefined'){ return new XMLHttpRequest(); // 检测Active对象是否存在 }else if(typeof ActiveXObject != 'undefined'){ if(typeof arguments.callee.activeXString != 'string'){ // IE中可能有3种不同版本的XML对象 var versions = ['MSXML2.XMLHttp.6.0','MSXML2.XMLHttp.3.0','MSXML2.XMLHttp']; } for(var 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.'); } }
2、发送请求(get请求为例)
var xhr = createXHR(); xhr.open('get', 'example.txt', false); //false表示同步 xhr.send(null); //没有数据发送,则写Null
3、接受服务器的响应
在学习如何接受服务器的响应前,先来了解XHR对象与之相关的属性:
通过检测readystatechage事件来获取readyState的值,等于4时表示所有数据已经接收完毕,可以进行服务器返回状态的检测了:
var xhr = createXHR(); xhr.onreadystatechange = function(){ if(xhr.readyState == 4){ // 因为有的浏览器会错误的报告204,所以这样书写 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);
4、设置发送XHR请求时的http头部信息
默认情况下会发送的http头部信息:
- Accept: 浏览器能够处理的内容类型
- Accept-Charset:浏览器能够显示的字符集
- Accept-Encoding: 浏览器能够处理的压缩编码
- Accept-Language: 浏览器当前设置的语言
- Connection:浏览器与服务器直接连接的类型
- Cookie: 当前页面设置的任何cookie
- Host:发出请求的页面所在的域
- Referer: 发出请求页面的URI
- User-Agent:浏览器的用户代理字符串
要发送自定义的请求的头部信息,必须在调用open()和send()之间调用setRequestHeader()方法:
var xhr = createXHR(); xhr.open('get','example.txt',true); xhr.setRequestHeader('MyHeader', 'MyValue'); xhr.send(null); // 获取相应的头部信息 var myHeader = xhr.getResponseHeader('MyHeader'); // 获取所有的头部信息 var allHeader = xhr.getAllResponseHeaders();
二、XMLHttpRequest2级
XMLHttpRequest 2级进一步发展了XHR,但并非所有的浏览器都完整实现了XMLHttpRequest 2级规范,下面介绍其中新增的部分内容:
1、FormData对象
使用POST方式发送表单时,需要先将表单序列化,并且设置http的Content-Type为applicaition/x-www-form-urlencoded(发送到服务器前,所有内容进行编码的意思);使用FormData对象可以简化操作:
var data = new FormData(document.forms[0]); xhr.send(data);
2、timeout属性
IE8为XHR添加了一个timeout属性,表示请求在等待响应多少毫秒后终止。
xhr.open('get','test.php',true); xhr.timeout = 1000;//1秒,仅用于IE8 xhr.ontimeout = function(){ alert('Request did not return in a second.'); } xhr.send(null);
3、overrideMimeType()方法
重写MIME类型,例如服务器返回的MIME类型是text/plain,但数据中包含的实际是XML。这个时候,responseXML属性是null。通过调用overrideMimeType()方法,可保证把响应当XML而非纯文本处理。
xhr.open('get','test.php',true); xhr.overrideMimeType('text/xml'); xhr.send(null);
三、跨资源共享
1、CORS
通过XHR实现Ajax通信的一个主要限制是跨域安全策略,即协议、域名、端口必须完全一致,才能访问。CORS(cross-origin resource sharing,跨域资源共享)是W3C的一个方案,定义了跨域访问时的沟通方式。其基本思想是,使用自定义的HTTP头让浏览器与服务器进行沟通,从而决定请求或响应应该成功还是失败。例如,在服务器端设置:Access-Control-Allow-Origin:* 或者Access-Control-Allow-Origin:指定的IP。
2、图像Ping
原理:利用img标签不存在跨域问题的特性,来与服务器进行简单、单项的跨域通信
缺点:只能发送get请求;无法访问服务器的响应文本
使用场景:跟踪用户点击页面或动态广告的曝光次数
var img = new Image(); img.onload = img.onerror = function(){ alert('done'); } img.src = "http://www.baidu.com";
3、JSONP
JSONP是JSON with padding的简写,是通过为动态<script>元素中的src属性指定URL来实现的(与img标签类似)。JSONP由两部分组成:回调函数和数据。例如:callback({'name':'Lillian'});
回调函数中的名字一般是在请求中指定,请求的实际数据是回调函数包裹着的数据。因为JSONP是有效的javascript代码,所以当请求完成后,即JSONP响应加载到页面后,就会立即执行。
优点:支持浏览器和服务器的双向通信
缺点:JSONP从其他域加载代码并执行,其他域的安全性不一定能保证;要确定JSONP请求是否失败,浏览器的事件处理程序支持的并不好。
function handleResponse(response){ // 请求完成后,代码会立刻执行 } var script = document.createElement('script'); script.src = 'http://testtest/json?callback=handleResponse'; document.body.insertBefore(script, document.body.firstChild);
三、Comet
Ajax是一种页面向服务器请求数据的技术,Comet是一种服务器向页面推送数据的技术。有两种实现方式:长轮询和流。
短轮询是页面向服务器发起请求后,无论数据是否有效,服务器都立即响应;长轮询是服务器会一直打开,直到有数据可以发送。
HTTP流在整个页面周期内只有一个HTTP连接。它是浏览器向服务器发送一个请求,而服务器保持连接打开,然后周期性的向浏览器发送数据。
四、SSE和WebSocket
SSE是围绕只读Comet交互推出的API或者模式,用于创建到服务器的单向连接,服务器可以通过这个连接发送任意的数据。
WebSocket是在一个单独的持久连接上提供全双工、双向通信。用自定义的ws协议取代了http协议,wss协议取代了https协议。