使用javascript來實現客戶端/服務器的通信,極大地擴展了javascript語言的功能。但是,使用這種強大功能的同時,也帶來了一些需要注意的問題。
在這一小節中,前兩個問題將分別討論使用ajax技術時“同源策略”的問題,以及使用xmlhttprequest對象時所帶來的activex控件問題。第三個問題將討論ajax的可用性問題,即ajax技術改變了頁面中的某些方面,并如何解決這些問題。
早在netscape navigator 2.0瀏覽器時代,javascript代碼就不能訪問非同源的腳本或者頁面。這是瀏覽器所遵循的一個重要的安全措施。否則,一些惡意代碼的編寫者就能在任何地方執行惡意的代碼。同源策略指的是,僅當兩個頁面的協議(http)、端口號(默認時為80端口)和主機名相同時,這兩個頁面才是同源的。
例如,下面這兩個頁面:
● 頁面1的位置為http://www.site.com/folder/mypage1.htm
● 頁面2的位置為http://www.site.com/folder10/mypage2.htm
根據同源策略的要求,這兩個頁面是同源的。因為這兩個頁面具有相同的主機名(www.site.com),使用了相同的協議(http),并訪問了相同的端口(這兩個頁面并沒有聲明端口,因此使用的是默認的80端口)。由于這兩個頁面是同源的,因此一個頁面中的javascript將可以訪問另一個頁面。
再如下面的兩個頁面:
● 頁面1的位置為http://www.site.com/folder/mypage1.htm
● 頁面2的位置為https://www.site.com/folder/mypage2.htm
顯然,這兩個頁面并不是同源的。雖然這兩個頁面的主機名和端口號是相同的,但是卻使用了不同的協議。頁面1使用的是http協議,而頁面2使用的是https協議。這一差異使得瀏覽器將這兩個頁面視為兩個不同的源。因此,其中一個頁面中的javascript將無法訪問另一個頁面。
那么,這與ajax技術有什么關系呢?由于ajax技術中大量使用了javascript,因此同源策略幾乎影響到ajax的每一方面。例如,由于同源策略的限制,xmlhttprequest對象將無法訪問任何非同源的文件。但是,我們可以采用一種很簡單方式來解決這一問題,即使用一個同源的頁面作為代理(proxy),通過該代理來獲取另一個非同源服務器上的數據。同源策略同樣影響到使用frame/iframe方式來實現的ajax技術,即使兩個頁面位于同一個框架集中,但是如果這兩個頁面不同源的話,javascript將無法在這兩個頁面之間實現交互。
xmlhttprequest對象的一個弊端在于它是一個activex控件,因此只有在windows系統的ie瀏覽器中才可以使用xmlhttprequest對象。盡管ie瀏覽器是當前市場占有率最高的瀏覽器,而且它的市場占有率短期內似乎不會發生什么改變。但是,由于在過去幾年中,圍繞 activex控件產生了很多的安全性問題,特別是很多惡意廣告軟件和間諜軟件通過用戶計算機對activex控件的信賴而安裝在用戶的計算機中。因此,activex控件的使用對用戶的計算機安全造成了一定的隱患。
由于人們對安全性問題越來越重視,microsoft采取了一些措施,以嚴格限制對activex控件或插件對象的訪問,這樣不但使瀏覽器變得更加安全,還有效地避免了惡意的攻擊。但是這樣一來,如果用戶完全禁用了activex控件,或者你的站點被標記為某一特定的安全區域,就可能使得activex控件對象無法創建,從而導致基于xmlhttprequest對象的ajax程序無法正常工作。
ajax技術打破了傳統web應用程序和web頁面的模式。ajax允許創建類似于普通桌面應用程序的web應用,而不是充滿了web味(webbish)的頁面。但是,ajax技術也存在一定的缺點,internet已經存在并發展了很多年,某些用戶可能已經習慣了傳統的web頁面。
因此,我們需要確保用戶能夠使用我們的web頁面,并以他們熟悉的方式來訪問頁面,在使用ajax技術時,不應給用戶造成挫折感。
瀏覽器的back和forward按鈕是用戶使用web的常用功能。在本章前面的內容中,我們已經討論過,在使用xmlhttprequest對象發起請求時,瀏覽器將不會在其歷史記錄中保存由xmlhttprequest對象發起的瀏覽記錄,這將使得瀏覽器的back和forward按鈕失效。為此,我們創建了一個使用隱藏iframe技術實現的ajax表單,以確保瀏覽器的back和forward按鈕的功能繼續有效。
但是,使用隱藏框架技術仍然存在一定的局限。在ie瀏覽器中,使用隱藏frame/iframe技術并沒有什么問題。ie瀏覽器將記錄每一個向服務器發起的請求,因此可以使用瀏覽器的back和forward按鈕在歷史記錄中前進或后退。但是對于其他的瀏覽器來說,情況并非如此,在其他的瀏覽器中則可能存在一些值得注意的怪癖。
例如firefox瀏覽器,如果我們直接在html頁面中添加<iframe>標記,則firefox瀏覽器也將在其歷史記錄中保存每一個請求的記錄。但是在早期版本的firefox瀏覽器中,如果我們使用dom方法動態地將<iframe>標記添加到html頁面中,firefox瀏覽器將不會記錄由iframe發起請求的瀏覽記錄。
另外,我們必須注意safari瀏覽器。safari瀏覽器并不記錄由iframe發起的請求。對于safari瀏覽器,必須使用一個傳統的框架集來實現ajax技術,以便safari瀏覽器能夠記錄瀏覽的歷史記錄。對于safari瀏覽器來說,隱藏的框架頁同樣可以實現iframe的功能,只不過使用框架集來代替了iframe。
與常見的應用程序一樣,web程序也可以通過用戶界面(ui)來提示用戶系統真正執行某種任務。例如,當用戶單擊了某一個超鏈接時,一個跳動的動畫將開始運行,在windows系統中,一個沙漏圖標將出現在鼠標指針的旁邊,并且通常在狀態欄中顯示瀏覽器正在加載頁面的信息。
這正是ajax技術特別是xmlhttprequest對象的另一個典型應用場景。而且這一功能非常容易實現:只需簡單地添加一個ui元素以告訴用戶某個任務正在運行,并在該任務完成之后將該ui元素移除即可。例如下面的代碼:
function requestcomplete(sresponsetext)
{
//do something with the data here
document.getelementbyid("divloading").style.display = "none";
}
var myrequest = new httprequest("http://localhost/myfile.txt",
requestcomplete);
document.getelementbyid("divloading").style.display = "block";//show that
we’re loading
myrequest.send();
上面的代碼使用了前面創建的httprequest類來發起一個對myfile.txt文件的請求。在發送請求之前,通過document.getelementbyid("divloading")方法獲取id號為divloading的<div/>元素。該<div/>元素將告訴用戶數據正在加載中。當請求已經完成時,則將<div/>元素隱藏,以便讓用戶知道數據加載過程已經完成。
在數據加載過程中,應該向用戶顯示相應的提示信息,以便用戶知道應用程序正在按他的請求執行某些操作。否則,當用戶單擊了超鏈接之后卻沒有任何及時的反應,用戶可能就會懷疑我們的應用程序是否在正常工作。
在理想情況下,我們所編寫的代碼每次都能正常運行。但是遺憾的是,我們不得不面對這樣的事實,使用ajax技術的頁面并不能總是為我們帶來ajax的好處,用戶的瀏覽器可能禁用了javascript,從而導致帶有ajax功能的頁面執行失敗。
解決這個問題的唯一辦法是:創建一個老式的web頁面,并使用老式的表單、超鏈接和其他html元素。然后,關閉這些html元素的默認行為,并使用javascript來添加相應的ajax功能。例如,對于下面這個超鏈接:
<a href="http://www.wrox.com" title="wrox publishing">wrox publishing</a>
這是一個普通得不能再普通的超鏈接。當用戶單擊該超鏈接時,將把用戶導航到http://www.wrox.com頁面。通過使用javascript,可以覆蓋(override)超鏈接的默認行為,并替換為我們所需要的功能。
<a href="http://www.wrox.com" title="wrox publishing"
onclick="return false;">wrox publishing</a>
實現這個功能的關鍵在于從超鏈接的onclick事件處理器中返回一個false值。我們可以在該事件處理器中執行任何我們所需要的代碼,只需最后返回一個false值即可。返回的false值將告訴瀏覽器當用戶單擊超鏈接時不執行任何默認的動作。如果用戶的瀏覽器禁用了javascript功能,則onclick事件處理器將被忽略,超鏈接將恢復到正常的行為。
作為一個經驗法則,最好先創建web頁面,再在頁面中添加相應的ajax功能。
新聞熱點
疑難解答
圖片精選