根據一個網頁能夠從任何網頁中加載圖像而不用擔憂使用跨域的原理, 咱們能夠動態的建立圖像, 使用他們的onload和onerror事件處理程序來肯定是否收到響應。javascript
動態的建立圖像常常用於圖像Ping。 圖像Ping是與服務器進行簡單的單向的跨域通訊的一種方式。php
請求的數據經過查詢字符串形式發送的,而響應能夠是任意內容, 但一般是像素圖或者204響應。 java
經過圖像Ping,瀏覽器得不到任何具體的數據, 可是經過偵聽load和error事件, 它能知道是何時接受的。web
var img = new Image(); img.onload = img.onerror = function() { alert("Done"); }; img.src = "http://ww.example.com/test?name=seacean";
圖像Ping最經常使用於跟蹤用戶點擊頁面或動態廣告曝光次數。算法
它有兩個主要的缺點:只能發送get請求,沒法訪問服務器的響應文本。所以, 圖像Ping只能用於瀏覽器與服務器間的單向通訊。json
JSONP是JSON with padding的簡寫,是應用json的一種新方法,在後來的Web服務中很是流行。api
callback({ "name": "Oli" });
JSONP由兩部分組成:回調函數和數據。跨域
回調函數是當響應到來時應該在頁面中調用的函數,回調函數的名字通常是在請求中指定的。數據就是傳入回調函數的json數據。瀏覽器
下面是以個JSONP的例子:緩存
http: //freegeoip.net/json/?callback=handleResponse //回調函數的名字就是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方式是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是爲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頭部請求, 以便服務器知道下次觸發那個事件。 在屢次鏈接的事件流中, 這種機制保證了瀏覽器可以以正確的順序接收到鏈接的數據段。
在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請求的資源要求每一次請求都要附帶通過相應算法計算獲得的驗證碼