1. 程式人生 > >【轉】Ajax的工作原理(面試)

【轉】Ajax的工作原理(面試)

Ajax的核心是JavaScript物件XmlHttpRequest。該物件在Internet Explorer 5中首次引入,它是一種支援非同步請求的技術。簡而言之,XmlHttpRequest使您可以使用JavaScript向伺服器提出請求並處理響應,而不阻塞使用者。

在建立Web站點時,在客戶端執行螢幕更新為使用者提供了很大的靈活性。下面是使用Ajax可以完成的功能:

* 動態更新購物車的物品總數,無需使用者單擊Update並等待伺服器重新發送整個頁面。

* 提升站點的效能,這是通過減少從伺服器下載的資料量而實現的。例如,在Amazon的購物車頁面,當更新籃子中的一項物品的數量時,會重新載入整個頁面,這必須下載32K的資料。如果使用Ajax計算新的總量,伺服器只會返回新的總量值,因此所需的頻寬僅為原來的百分之一。

* 消除了每次使用者輸入時的頁面重新整理。例如,在Ajax中,如果使用者在分頁列表上單擊Next,則伺服器資料只重新整理列表而不是整個頁面。

* 直接編輯表格資料,而不是要求使用者導航到新的頁面來編輯資料。對於Ajax,當用戶單擊Edit時,可以將靜態表格重新整理為內容可編輯的表格。使用者單擊Done之後,就可以發出一個Ajax請求來更新伺服器,並重新整理表格,使其包含靜態、只讀的資料。

一切皆有可能!但願它能夠激發您開始開發自己的基於Ajax的站點。然而,在開始之前,讓我們介紹一個現有的Web站點,它遵循傳統的提交/等待/重新顯示的範例,我們還將討論Ajax如何提升使用者體驗。

Ajax可用於那些場景?——一個例子:MSN Money頁面

前幾天,在瀏覽MSN Money頁面的時候,有一篇關於房地產投資的文章引起了我的好奇心。我決定使用站點的“Rate this article”(評價本文)功能,鼓勵其他的使用者花一點時間來閱讀這篇文章。在我單擊vote按鈕並等待了一會兒之後,整個頁面被重新整理,在原來投票問題所在的地方出現了一個漂亮的感謝畫面。

而Ajax能夠使使用者的體驗更加愉快,它可以提供響應更加靈敏的UI,並消除頁面重新整理所帶來的閃爍。目前,由於要重新整理整個頁面,需要傳送大量的資料,因為必須重新發送整個頁面。如果使用Ajax,伺服器可以返回一個包含了感謝資訊的500位元組的訊息,而不是傳送26,813位元組的訊息來重新整理整個頁面。即使使用的是高速Internet,傳送26K和1/2K的差別也非常大。同樣重要的是,只需要重新整理與投票相關的一小節,而不是重新整理整個螢幕。

讓我們利用Ajax實現自己的基本投票系統。

原始的Ajax:直接使用XmlHttpRequest

如上所述,Ajax的核心是JavaScript物件XmlHttpRequest。下面的示例文章評價系統將帶您熟悉Ajax的底層基本知識:http://tearesolutions.com/ajax-demo/raw-ajax.html。注:如果您已經在本地WebLogic容器中安裝了ajax-demo.war,可以導航到http://localhost:7001/ajax-demo/raw-ajax.html,

瀏覽應用程式,參與投票,並親眼看它如何運轉。熟悉了該應用程式之後,繼續閱讀,進一步瞭解其工作原理細節。

首先,您擁有一些簡單的定位點標記,它連線到一個JavaScriptcastVote(rank)函式。

 
function castVote(rank) {

var url = “/ajax-demo/static-article-ranking.html”;

var callback = processAjaxResponse;

executeXhr(callback, url);

}


該函式為您想要與之通訊的伺服器資源建立一個URL並呼叫內部函式executeXhr,提供一個回撥JavaScript函式,一旦伺服器響應可用,該函式就被執行。由於我希望它執行在一個簡單的Apache環境中,“cast vote URL”只是一個簡單的HTML頁面。在實際情況中,被呼叫的URL將記錄票數並動態地呈現包含投票總數的響應。

下一步是發出一個XmlHttpRequest請求:

function executeXhr(callback, url) {

// branch for native XMLHttpRequest object

if (window.XMLHttpRequest) {

req = new XMLHttpRequest();

req.onreadystatechange = callback;

req.open(“GET”, url, true);

req.send(null);

} // branch for IE/Windows ActiveX version

else if (window.ActiveXObject) {

req = new ActiveXObject(“Microsoft.XMLHTTP”);

if (req) {

req.onreadystatechange = callback;

req.open(“GET”, url, true);

req.send();

}

}

}

 

如您所見,執行一個XmlHttpRequest並不簡單,但非常直觀。和平常一樣,在JavaScript領域,大部分的工作量都花在確保瀏覽器相容方面。在這種情況下,首先要確定XmlHttpRequest是否可用。如果不能用,很可能要使用Internet Explorer,這樣就要使用所提供的ActiveX實現。

executeXhr()方法中最關鍵的部分是這兩行:

req.onreadystatechange = callback;
req.open(“GET”, url, true);


第一行定義了JavaScript回撥函式,您希望一旦響應就緒它就自動執行,而req.open()方法中所指定的“true”標誌說明您想要非同步執行該請求。

一旦伺服器處理完XmlHttpRequest並返回給瀏覽器,使用req.onreadystatechange指派所設定的回撥方法將被自動呼叫。

function processAjaxResponse() {

// only if req shows “loaded”

if (req.readyState == 4) {

// only if “OK”

if (req.status == 200) {

502 502′votes’).innerHTML = req.responseText;

} else {

alert(“There was a problem retrieving the XML data:

” +

req.statusText);

}

}

}


該程式碼相當簡潔,並且使用了幾個幻數,這使得難以一下子看出發生了什麼。為了弄清楚這一點,下面的表格(引用自http://developer.apple.com/internet/webcontent/xmlhttpreq.html)列舉了常用的XmlHttpRequest物件屬性。

屬性

描述

onreadystatechange

每次狀態改變所觸發事件的事件處理程式

readyState

物件狀態值:

* 0 = 未初始化(uninitialized)

* 1 = 正在載入(loading)

* 2 = 載入完畢(loaded)

* 3 = 互動(interactive)

* 4 = 完成(complete)

responseText

從伺服器程序返回的資料的字串形式

responseXML

從伺服器程序返回的DOM相容的文件資料物件

status

從伺服器返回的數字程式碼,比如404(未找到)或200(就緒)

statusText

伴隨狀態碼的字串資訊

現在processVoteResponse()函式開始顯示出其意義了。它首先檢查XmlHttpRequest 的整體狀態以保證它已經完成(readyStatus == 4),然後根據伺服器的設定詢問請求狀態。如果一切正常(status == 200),就使用innerHTML屬性重寫DOM的“votes”節點的內容。

既然您親眼看到了XmlHttpRequest物件是如何工作的,就讓我們利用一個旨在簡化JavaScript與Java應用程式之間的非同步通訊的框架來對具體的細節進行抽象。

Ajax: DWR方式

按照與文章評價系統相同的流程,我們將使用Direct Web Remoting(DWR)框架實現同樣的功能。

假定文章和投票結果儲存在一個數據庫中,使用某種物件/關係對映技術來完成抽取工作。為了部署起來儘可能地簡單,我們不會使用資料庫進行永續性儲存。此外,為使應用程式儘可能通用,也不使用Web框架。相反,應用程式將從一個靜態HTML檔案開始,可以認為它由伺服器動態地呈現。除了這些簡化措施,應用程式還應該使用Spring Framework關聯一切,以便輕鬆看出如何在一個“真實的”應用程式中使用DWR。

現在應該下載示例應用程式並熟悉它。該應用程式被壓縮為標準的WAR檔案,因此您可以把它放置到任何一個Web容器中——無需進行配置。部署完畢之後,就可以導航到http://localhost:7001/ajax_demo/dwr-ajax.html來執行程式。

可以檢視HTML原始碼,瞭解它如何工作。給人印象最深的是,程式碼如此簡單——所有與伺服器的互動都隱藏在 JavaScript物件ajaxSampleSvc的後面。更加令人驚訝的是,ajaxSampleSvc服務不是由手工編寫而是完全自動生成的!讓我們繼續,看看這是如何做到的。

引入DWR

如同在“原始的Ajax”一節所演示的那樣,直接使用XmlHttpRequest建立非同步請求非常麻煩。不僅JavaScript程式碼冗長,而且必須考慮伺服器端為定位Ajax請求到適當的服務所需做的工作,並將結果封送到瀏覽器。

設計DWR的目的是要處理將Web頁面安裝到後端服務上所需的所有資訊管道。它是一個Java框架,可以很輕鬆地將它插入到Web應用程式中,以便JavaScript程式碼可以呼叫伺服器上的服務。它甚至直接與Spring Framework整合,從而允許使用者直接向Web客戶機公開bean。

DWR真正的巧妙之處是,在使用者配置了要向客戶機公開的服務之後,它使用反射來生成JavaScript物件,以便 Web頁面能夠使用這些物件來訪問該服務。然後Web頁面只需接合到生成的JavaScript物件,就像它們是直接使用服務一樣;DWR無縫地處理所有有關Ajax和請求定位的瑣碎細節。


文章來源:http://www.kanzhun.com/mianshiti/936.html?sid=mail_18200_1_detail&ka=mail-18200-1detail1