中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

掙脫瀏覽器的束縛(6) - AJAX也跨域名

發布時間:2020-04-14 05:18:09 來源:網絡 閱讀:695 作者:jeffz 欄目:web開發
  標題有些唬人的成分,因為這里跨的只是子域名。
   事情的經過是這樣的,還是那個個人門戶網站。其中有個功能就是RSS訂閱,每個訂閱作為一個模塊出現在頁面上。如果一個用戶訂閱了比較多的RSS,則在 打開頁面時所有的RSS模塊就會開始加載,這時候可能就會需要十幾秒甚至更長的時間才能加載完畢。這時,如果用戶需要作別的AJAX操作——比如保存頁面 設置——那么長時間的等待就不可避免了,誰讓瀏覽器對于相同域名只能同時存在兩個連接呢?不過這可不是一個好的用戶體驗,那么我們需要怎么做呢?
   第一種做法可能比較容易想到,我們可以自己編寫代碼維護一個Priority Queue,為每個請求附加一個“優先級”信息,這樣我們就可以把重要的請求率先發出。這樣就可以在一定程度上解決用戶的等待問題。可惜這個方法還是無法 突破兩個連接的限制。于是第二種做法,我們就要設法突破兩個連接的限制了。如果能夠向別的域名發出AJAX請求,不也就能避免重要的請求被大量的請求所阻 塞了嗎?
  我們還是從頭看起,一點一點地來解決這個問題。
 
阻塞的AJAX請求
  我們先來證實一下請求的阻塞情況吧。我們使用如下的代碼:
連續發起三個請求
function simpleRequest()
{
var request = new XMLHttpRequest();
request.open("POST", "Script.ashx");
request.send(null);
}

function threeRequests()
{
simpleRequest();
simpleRequest();
simpleRequest();
}
 
  當執行threeRequests時就會連續發出3個相同域名的請求,還是通過統計圖表來查看阻塞的效果(如圖11):

掙脫瀏覽器的束縛(6) - AJAX也跨域名
  每個請求需要花費1.5秒的時間。很明顯,第三個請求必須等到第一個請求結束之后才能執行,因此總共需要進行3秒多鐘才能執行完畢。我們要改變的就是這個狀況。
 
傳統的跨域名異步請求解決方案
  AJAX安全性的唯一保證,似乎就是對于跨 域名(Cross-Domain)AJAX請求的限制。除非打開本地硬盤的網頁,或者在IE中將跨域名傳輸數據的限制打開,否則向其他域名發出AJAX請 求都會被禁止。而且對于跨域名的判斷非常嚴格,不同的子域名,或者相同域名的不同端口,都會被認作是不同的域名,我們不能向它們的資源發出AJAX請求。
  從表面上看起來似乎沒有辦法打破這個限制,還好我們有個救星,那就是iframe!
  iframe雖然不在標準中出現,但是由于 它實在有用,FireFox也“不得不”對它進行了支持(類似的還有innerHTML)。網上已經有一些跨域名發出異步請求的做法,但是它們實在做的不 好。它們的簡單工作原理如下:在另一個域名下放置一個特定的頁面文件作為Proxy,主頁面將異步請求的信息通過Query String傳遞入iframe里的Proxy頁面,Proxy頁面在AJAX請求執行完畢后將結果放在自己location的hash中,而主頁面會對 iframe的src的hash值進行輪詢,一旦發現它出現了改變,則通過hash值得到需要的信息。
  這個方法的實現比較復雜,而且功能有限。在 IE和FireFox中,對于URL的長度大約可以支持2000個左右的字符。對于普通的需求它可能已經足夠了,可惜如果真要傳遞大量的數據,這就遠遠不 夠了。與我們一會兒要提出的解決方案相比,可能它唯一的優勢就是能夠跨任意域名進行異步請求,而我們的解決方案只能突破子域名的限制。
  那么現在來看看我們的做法!
 
優雅地突破子域名的限制
  我們突破子域名限制的關鍵還是在于iframe。
  iframe是的好東西,我們能夠跨過子域 名來訪問iframe里的頁面對象,例如window和DOM結構,包括調用JavaScript(通過window對象)——我們將內外頁面的 document.domain設為相同就可以了。然后在不同子域名的頁面發起不同的請求,把結果通過JavaScript進行傳遞即可。唯一需要的也僅 僅是一個簡單的靜態頁面作為Proxy而已。
  我們現在就來開始編寫一個原形,雖然簡單,但是可以說明問題。
  首先,我們先來編寫一個靜態頁面,作為放在iframe里的Proxy,如下:
SubDomainProxy.html
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<title>Untitled Page</title>
<script type="text/javascript" language="javascript">
document.domain = "test.com";

function sendRequest(method, url)
{
var request = new XMLHttpRequest();
request.open(method, url);
request.send(null);
}
</script>
</head>
<body>

</body>
</html>
 
  然后我們再編寫我們的主頁面:
[url]http://www.test.com/Default.html[/url]
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Untitled Page</title>
<script type="text/javascript" language="javascript">
document.domain = "test.com";

function simpleRequest()
{
var request = new XMLHttpRequest();
request.open("POST", "Script.ashx");
request.send(null);
}

function crossSubDomainRequest()
{
var proxy = document.getElementById("iframeProxy").contentWindow;
proxy.sendRequest('POST', 'http://sub0.test.com/Script.ashx');
}

function threeRequests()
{
simpleRequest();
simpleRequest();
crossSubDomainRequest();
}
</script>
</head>
<body>
<input type="button" value="Request" onclick="threeRequests()" />
<iframe src="http://sub0.test.com/SubDomainProxy.html" style="display:none;"
id="iframeProxy"></iframe>
</body>
</html>
 
  當執行threeRequests方法時,將會同時請求[url]http://www.test.com[/url]以及[url]http://sub0.test.com[/url]兩個不同域名下的資源。很明顯,最后一個請求已經不會受到前兩個請求的阻塞了(如圖12):

掙脫瀏覽器的束縛(6) - AJAX也跨域名
圖12:不同域名的請求不會被阻塞
  令人滿意的結果!
  雖說只能突破子域名,但是這已經足夠了,不 是嗎?我們為什么要強求任意域名之間能夠異步通訊呢?更何況我們的解決方案是多么的優雅!在下一篇文章中,我們將會為ASP.NET AJAX客戶端實現一個完整的CrossSubDomainRequestExecutor,它會自動判斷是否正在發出跨子域名的請求,并選擇AJAX請 求的方式。這樣,客戶端的異步通訊層就會對開發人員完全透明。世上還會有比這更令人愉快的事情嗎?:)
 
注意事項
  可能以下幾點值得一提:
  • 我在出現這個想法之后也作了一些嘗試,最后發現創建XMLHttpRequest對象,調用open方法和send方法都必須在iframe中的頁面中執行才能夠在IE和FireFox中成功發送AJAX請求。
  • 在上面的例子中,我們向子域名請求的的路徑是[url]http://sub0.test.com/Script.ashx[/url]。請注意,完整的子域名不可以省略,否則在FireFox下就會出現權限不夠的錯誤,在調用open方法時就會拋出異常——似乎FireFox把它當作了父頁面域名的資源了。
  • Windows Live Contacts Gadget使用了一種叫做Channel的技術,用于解決跨任意域名傳遞數據的問題,我相當佩服微軟技術人員的創造力。Channel技術是一種優秀的 解決跨域名異步請求問題的解決方案,而且如果將它封裝成了組件,那么使用起來也會相當優雅(似乎微軟已經準備這么做了)。不過它和我們現在需要解決的問題 并不相同,如果有機會的話,我也會詳細的解釋一下Channel技術——但不是現在,因為我覺得我還沒有完全理解這個技術本身。
向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

高唐县| 嵊州市| 洪泽县| 唐河县| 乌审旗| 金阳县| 玉山县| 新和县| 两当县| 泰州市| 梅州市| 二手房| 临邑县| 镇雄县| 西贡区| 洮南市| 额敏县| 家居| 平谷区| 乡宁县| 昆山市| 安泽县| 斗六市| 平罗县| 疏附县| 监利县| 沽源县| 陆良县| 温州市| 广西| 南乐县| 高唐县| 开鲁县| 海丰县| 兴和县| 皮山县| 平顶山市| 石台县| 彝良县| SHOW| 牡丹江市|