#什么是Ajax?
浏览器其实只是封装了一个Socket调用而已。XMLHttpRequest作为封装这个Socket的Proxy。
Socket的工作流程:
Ajax的工作流程:
创建XMLHttpRequest对象-->设置连接的相关参数open(method,async)-->发送数据send([string])-->处理接受到的数据onreadystatechange( )
var xmlhttp = new XMLHttpRequest(); xmlhttp.onreadystatechange = function() { // xmlhttp.readyState // xmlhttp.status } xmlhttp.open("GET","/ajax/demo_get.PHP",true); xmlhttp.send();
var xhr = new XMLHttpRequest(),type = type || "GET",data = data || null; xhr.onreadystatechange = function() { if (xhr.readyState == 4) { receive(xhr.responseText); xhr.onreadystatechange = null; } }; xhr.open(type,url,true); //IE的ActiveXObject("Microsoft.XMLHTTP")支持GET方法发送数据, //其它浏览器不支持,已测试验证 xhr.send(type == "GET" ? null: data); }; var timer = setInterval(function() { polling(); },1000);
Ajax发送的内容仍然是基于HTTP协议的请求。理论上Ajax发送一个请求和你在地址栏里面输入请求是一模一样的。服务器应该根本就不知道什么是Ajax,服务器只处理HTTP请求。
#什么是Reverse Ajax
先谈谈为什么要Reverse Ajax:
因为HTTP协议是无状态的,即请求完数据后就关闭了连接。如果服务器有新的数据,浏览器是无法知道的,必须主动去查询才能知道。又因为Ajax是基于HTTP的,所以Ajax请求在缺省情况下也是无状态的,且只能从客户端向服务器端发出请求。(可以通过使用技术模拟服务器端和客户端之间的响应式通信来绕过这一限制)。
为了尽快地获得服务器端事件,我们只能使用粗暴的HTTP轮询来完成任务。轮询的间隔(两次请求相隔的时间)必须尽可能地小。
- 优点:很容易实现,不需要任何服务器端的特定功能,且在所有的浏览器上都能工作。
- 缺点:如果间隔减小的话,客户端浏览器就会发出更多的请求,这些请求中的许多都不会返回任何有用的数据,而这将会白白地浪费掉带宽和处理资源。
有一个叫捎带轮询(piggyback polling)的实现方式是一种比轮询更加聪明的做法。它会删除掉所有非必需的请求(没有返回数据的请求)。不存在时间间隔,客户端在需要的时候向服务器端发送请求。不同之处在于响应的那部分上,响应被分成两个部分:对请求数据的响应和对服务器事件的响应,如果任何一部分有发生的话,在实现piggyback技术时,通常针对服务器端的所有Ajax请求可能会返回一个混合的响应。
- 优点:没有不返回数据的请求。因为客户端对何时发送请求做了控制,对资源的消耗较少。该方法也可用在所有的浏览器上,不需要服务器端的特殊功能。
- 缺点:当累积在服务器端的事件需要传送给客户端时,你却一点都不知道,因为这需要一个客户端行为来请求它们。
我们回到原点,为什么要关闭连接然后再不停的建立连接呢? 为什么不建立一个时间非常长的连接呢?
#Comet
Comet 是一种Web应用程序架构。可以说,它不是一种技术,而是一种思想,只是这种思想采用了已有的技术去实现。在这种思想里,客户端(Client)不需要显式地向服务器端(Server)发出请求,Server会在其数据发生变化的时候主动将数据异步发送给Client,从而使Client能够及时更新数据并呈现给用户。它不同于传统的Web,也不同于当前流行的Ajax,这种思想非常架构思想非常适合event-driven(事件驱动)式的Web应用和对交互性及实时性要求很强的应用,比如股票交易,聊天室,Web IM,网游等。
最常见的有下面两种方式:
1. HTTP 长轮询( HTTP Long Polling ) : Javascript 在处理完服务器返回的信息后再次发出请求,重新建立连接。不同于一般的 Ajax , Javascript 请求 Server ,无数据时 Server 不中断请求( still loading) ,在一定时间内获取到数据后,返回请求,又在 获取数据后再次发出请求,由此轮询。需要注意的是请求的间隔时间以及每次请求的最长 Loading 时间。做个比喻, 如果 轮询 是排队买东西,那么长轮询就是排队上厕所。买东西的话,丢下钱就可以拿东西走了,但是上厕所就不一样,有些人说不定便秘半个小时都出不来。如果只用轮询去做Web通信,那服务器就鸭梨山大了,它需要一直做接受和断开HTTP请求的操作。就像卖热销产品的店员就没有公共厕所管理员那么轻松。ajax实现长轮询时,就是在xhr对象关闭连接的时候马上又给接上:
var longPoll = function(type,url) { var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function() { // 状态为 4,数据传输完毕,重新连接 if (xhr.readyState == 4) { receive(xhr.responseText); xhr.onreadystatechange = null; //递归 longPoll(type,url); } }; xhr.open(type,true); xhr.send(); }
只要服务器断开连接,客户端马上连接,不让有一刻的休息时间,这就是长轮询。
- 优点:不会有很大的通信量,而且数据接收非常及时,并且无中断;
- 缺点:会产生进度条的Loading状态并一直存在,用户使用体验很不好。在Google Talk中,通过Htmlfile Active解决了IE下的进度条显示问题;保持长期链接也非常耗服务器资源;
#HTML5Server-Sent Events
Server-Sent Events是基于HTTP streaming的。如上所述,响应会一直打开,当服务器端有事件发生的时候,事件会被写入响应中。
#HTML5 WebSocket
WebSocket 启用了双向的全双工通信信道,许多浏览器(Firefox、Google Chrome 和 Safari)都已对此做了支持。连接会保持在活动状态,可以使用 JavaScript 来写入和接收数据,就像是在使用一个原始的TCP套接口一样。WebSocket URL的起始输入是ws://或是wss://(在SSL上),从这个ws和wss上可以想到,WebSocket已经不是建立在HTTP协议之上了!
- 优点:功能强大、双向、低延迟,且易于处理错误。不像 Comet 长轮询那样有许多的连接。它的API 也很容易使用,无需另外的层就可以直接使用,而Comet 则需要一个很好的库来处理重连接、超时、Ajax请求、确认以及选择不同的传输(Ajax 长轮询和 jsonp 轮询)。
- 缺点:是一个来自 HTML5 的新规范,还没有被所有的浏览器支持。没有请求作用域(request scope)(因为WebSocket是一个TCP套接口而不是一个HTTP请求),有作用域的请求服务,比如说 Hibernate 的 SessionInViewFilter,就不太容易使用。
var ws = new WebSocket("ws://www.example.com:8888"); ws.onopen = function(evt) {}; ws.onmessage = function(evt) { deal(evt.data); }; ws.onclose = function(evt) {}; //ws.close();