AJAX對象調用(XML HTTP Request)

來源:互聯網
上載者:User
ajax|request|xml|對象
  1. 作者:Jim Ley(首頁)
  2. 譯者:Sheneyan(子烏)(首頁)
  3. 時間:2006.1.29
  4. 英文原文:http://jibbering.com/2002/4/httprequest.html
  5. 譯文地址:http://sheneyan.com/g.php/tech/article/ajax/httprequest.html

子烏註:這篇文章我想看過的人很多,翻譯的版本也有許多,我之所以要再來翻譯一次,是因為這篇文章的時效性(看下一段作者說明),以及文字的優雅。文字的時效性,它居然是2006年1月再次更改的版本,也就是說,我也許就是第一個翻譯這個版本的人哦:P。文字的優雅,有能力、有空還是得看看原文,那英文的美感,在類似的技術文章中算很少見的(也許是我少見多怪,等我看多了就不會這樣了~)

  這篇文章寫於2002年4月,由於這個對象最終會變得越來越流行,我已經決定修改並更新這篇文章。2002版仍然可以線上閱讀,同樣的還有2004年9月版和2005年8月版。你正在閱讀的是2006年1月版。

  在windows上的Internet Explorer,Mac OS-X上的Safari,跨平台的Mozilla,KDE上的Konqueror,Java寫的IceBrowser,以及另一個跨平台的Opera(包括Symbian)都為用戶端的javascript指令碼提供了一個方法來產生HTTP請求。卑微的出身和少許推崇者的古怪命名,最終成長為在某些領域裡的核心技術,它叫作“AJAX”(欣賞一下原文:From the humble begins as an oddly named object with few admirers, it's blossomed to be the core technology in something called AJAX)。 [腳註1].

  這個對象讓許多事情變得比原來優雅、簡潔,並引入了一些在其他方面也一樣重要的東西,比如HEAD請求來看一個資源的最後修改時間,或者只是看它是否存在。它讓你的編碼(scripting?)的選擇更加靈活,允許POST提交,比如PUT、Delete等等操作的可能性而不需要頁面的改變。這些方法日益廣泛地應用於建立類似G-Mail的更強大提供更迅捷(snappier)使用者介面卻使用更少頻寬的web應用程式。

為什麼叫做“XML”HTTP Request對象?

  雖然這個對象被叫做“XML HTTP Request對象”,但它並不只局限於使用XML,它能夠請求或發送任何類型的文檔,雖然對於javascript來說,處理二進位流很成問題。

建立對象

  在Internet Explorer裡,你通過new ActiveXObject("Msxml2.XMLHTTP")new ActiveXObject("Microsoft.XMLHTTP")取決於安裝的MSXML版本)來建立這個對象。在Mozilla和Sarafi中(以及未來支援這個對象的類似它們倆的瀏覽器(UA,User Agent)),你使用new XMLHttpRequest(),而IceBrowser使用另外一個方法:window.createRequest()

  這意味著你需要在不同的瀏覽器上展現不同的指令碼(子烏註:小小抱怨一句,我還是覺得這點小小麻煩比起css的相容來說,簡單多了。。。。這隻是個人看法,也許過幾個月,我熟悉了css,就不會發這種牢騷了~),在一個瀏覽器上能夠幹得好好的代碼,在另外一個上面八成會出錯。下面的指令碼解決了這個問題,而且如果它不支援,變數xmlhttp將被設定為false並允許恰當的錯誤資訊,並在這個對象停用時候降低要求(degradtion),使用其他普通的http傳輸方法。留有後路是很重要的,即使在ie中,這個對象也經常由於安全設定的略微修改(通常是由於ie的入侵漏洞造成的)而被禁止。當你真的無法實現功能的時候而需要提供低等級的支援時,底下是一些方法。我建議是提供另一個變通的頁面。比如GMail確保說他們在未來(子烏註:呃。。。這文章是2002年寫的,那時候gmail還沒實現該功能)會提供一個更安全的版本,很有可能是完全沒有javascript--完全的退化。

var xmlhttp=false;   
/*@cc_on @*/ 
/*@if (@_jscript_version >= 5) 
// JScript提供的條件編譯讓我們能夠應付舊的ie版本,以及由於安全原因無法建立對象 
try { 
  xmlhttp = new ActiveXObject("Msxml2.XMLHTTP"); 
 } catch (e) { 
  try { 
   xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); 
  } catch (E) { 
   xmlhttp = false; 
  } 
 } 
@end @*/ 
if (!xmlhttp && typeof XMLHttpRequest!='undefined') {  
    try {  
        xmlhttp = new XMLHttpRequest();  
    } catch (e) {  
        xmlhttp=false;  
    }  
}  
if (!xmlhttp && window.createRequest) {  
    try {  
        xmlhttp = window.createRequest();  
    } catch (e) {  
        xmlhttp=false;  
    }  
}  

我如何提出一個請求?

  提出一個HTTP請求非常簡單。你告訴XML HTTP request對象你需要提出什麼類型的HTTP請求以及你要請求的URL。提供一個函數給它在請求完成的時候調用,以及最後,你需要在這個請求的主體中發送的內容(如果有的話)。

  下面的指令碼建立了一個針對相對連結(相對於請求頁面)“text.txt”的GET請求。它提供了一個可供調用的函數,當readyState屬性每次變化的時候它都將被調用,而當該屬性值成為4的時候--意味著載入完成,它使用一個alert來顯示responseText給使用者。

 xmlhttp.open("GET", "test.txt",true);xmlhttp.onreadystatechange=function() {if (xmlhttp.readyState==4) {alert(xmlhttp.responseText)}}xmlhttp.send(null)

提出一個HEAD請求

  子烏註:我會將header翻譯成前序,HEAD保持原文,resource翻譯成資源。個人感覺前序比較能體現header的原義。……嗯?你不知道前序是啥??這個不是報紙頭。如果你瞭解底層訊息的定義,你就會知道,一條訊息,不管是email,或者是簡訊,都會至少有兩個部分:前序和報文,前序中包含著這條訊息的資訊,而報文則是本文。這是大概解釋,還是不清楚的話就去google吧……

  對於一個HEAD請求,伺服器指揮返回指定資源的前序,而不包括資源本身,這意味著你能夠在不下載一個文檔的情況下得知該文檔的Content-Type或者Last-Modified。

一個典型的HEAD請求也許會返回類似底下的內容:

HTTP/1.1 200 OK
Server: Microsoft-IIS/4.0
Cache-Control: max-age=172800
Expires: Sat, 06 Apr 2002 11:34:01 GMT
Date: Thu, 04 Apr 2002 11:34:01 GMT
Content-Type: text/html
Accept-Ranges: bytes
Last-Modified: Thu, 14 Mar 2002 12:06:30 GMT
ETag: "0a7ccac50cbc11:1aad"
Content-Length: 52282

  要提出HEAD請求,你只需要簡單將第一個參數替換成HEAD,然後就可以使用getAllResponseHeaders擷取前序或者使用getResponseHeader("Name")取得單獨的前序。

xmlhttp.open("HEAD", "/faq/index.html",true);xmlhttp.onreadystatechange=function() {if (xmlhttp.readyState==4) {alert(xmlhttp.getAllResponseHeaders())}}xmlhttp.send(null)

使用HEAD請求,找到另一個檔案的最後修改時間。

  HEAD請求的用途之一,就是擷取某個url的修改時間,將之前的例子擴充一下,你將得到如下代碼:

 xmlhttp.open("HEAD", "/faq/index.html",true);xmlhttp.onreadystatechange=function() {if (xmlhttp.readyState==4) {alert("檔案最後修改時間 : "+xmlhttp.getResponseHeader("Last-Modified"))}}xmlhttp.send(null)

一個URL是否存在?

  另一個簡單用途是判斷URL是否存在,在HTTP中,HEAD和GET請求會返回集中狀態碼,200代表成功,404代表失敗,還有一些代表別的含義。查看HTTP狀態碼擷取詳細的解釋。xmlhttp對象使用status屬性來告訴你這個狀態。

 xmlhttp.open("HEAD", "/faq/index.html",true);xmlhttp.onreadystatechange=function() {if (xmlhttp.readyState==4) {if (xmlhttp.status==200) alert("URL 存在!")else if (xmlhttp.status==404) alert("URL 不存在!")else alert("狀態是 "+xmlhttp.status)}}xmlhttp.send(null)

無重新整理調用服務端指令碼

  在HTML中,表單是一種調用服務端指令碼的方法,它們會強制頁面重新整理,而這對使用者來說通常並不是非常的友好。使用Http Request,你能夠在不重新整理頁面的前提下呼叫指令碼,並且在XML HTTP Request對象停用時候還能退而使用表單。

<%a=+(Request.QueryString('a')+'')b=+(Request.QueryString('b')+'')if (isNaN(a) || isNaN(b)) {a='';b='';total='' }else {total=a+b}acc=Request.ServerVariables('HTTP_ACCEPT')+''if (acc.indexOf('message/x-jl-formresult')!=-1) {Response.Write(total)} else {%><script src="xmlhttp.js" type="text/javascript"></script><script>function calc() {frm=document.forms[0]url="add.1?a="+frm.elements['a'].value+"&b="+frm.elements['b'].valuexmlhttp.open("GET",url,true);xmlhttp.onreadystatechange=function() {if (xmlhttp.readyState==4) {document.forms[0].elements['total'].value=xmlhttp.responseText}}xmlhttp.setRequestHeader('Accept','message/x-jl-formresult')xmlhttp.send()return false}</script><form action="add.1" method="get" ><input type=text name=a value="<%=a%>"> + <input type=text name=b value="<%=b%>">= <input type=text name=total value="<%=total%>"><input type=submit value="Calculate"></form><%}%>

上面的樣本使用了asp的jscript作為服務端語言,HTTP ACCEPT前序被用來告訴服務端需要發送回什麼樣的響應--完整的頁面或者只是結果。這個HTTP ACCEPT前序用來告訴服務端用戶端會接受什麼樣的mime-types,通常它會是一些類似 text/html的內容。這裡我們告訴它我們只接受message/x-jl-formresult,所以伺服器知道它是我們的用戶端(或者其他知道message/x-jl-formresult的用戶端)提出的請求。

  另一個判斷返回內容的方法是通過你發送給伺服器的資料的類型推斷,你也可以簡單將表單提交給xmlhttp request的url變換一下。無論你怎麼作,保留對可能存在的不支援xmlhttp request的瀏覽器的向下相容是很明智的。

使用JSON作為傳輸語言

  雖然XML能夠被用於編碼(encode)你用這個對象取回的資料,並通過responseXML來訪問資料,但是XML還是不能被很好的支援,一些瀏覽器要求資源的內容類型必須是兩種可能的XML mime-type之一:text/xmlapplication/xml才能夠被接受,而且你處理的XML永遠可能會出現格式良好問題。JSON是一個很好的替換技術,它解析速度很快,而且,在指令碼中訪問,速度快得多得多。

  我在我的Flight Routeplanner中使用了JSON來尋找航班的資訊,比如London Heathrow,你能夠輕易的將返回的JSON使用new Function初始函數轉換成一個指令碼對象,這個對象將檢查狀態,如果從iata代碼中尋找航班失敗的話,將返回一個404給指令碼(it checks the status as the script returns 404 if it fails to find an airport with that iata code)。

 xmlhttp.open("GET","/routeplanner/airport.1?LHR",true);xmlhttp.onreadystatechange=function() {if (xmlhttp.readyState==4) {if (xmlhttp.status!=404) {var local=new Function("return "+xmlhttp.responseText)();alert("Code - Name\n"+local[0].id+' - '+local[0].name);} else {alert("Airport not found");}}}xmlhttp.send(null);

使用XMLHTTP操作GOOGLE的SOAP API

  Google針對它的資料庫提供了一個SOAP介面。你為了發出請求,需要註冊一個可以每天使用1000次的key。然後你需要自己解析返回的XML檔案。

 search="Word"xmlhttp.open("POST", "http://api.google.com/search/beta2",true);xmlhttp.onreadystatechange=function() {if (xmlhttp.readyState==4) {alert(xmlhttp.responseText)}}xmlhttp.setRequestHeader("Man", "POST http://api.google.com/search/beta2 HTTP/1.1")xmlhttp.setRequestHeader("MessageType", "CALL")xmlhttp.setRequestHeader("Content-Type", "text/xml")xmlhttp.send("<?xml version='1.0' encoding='UTF-8'?>"+"\n\n"+"<SOAP-ENV:Envelope"+' xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"'+' xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"'+' xmlns:xsd="http://www.w3.org/1999/XMLSchema">'+'<SOAP-ENV:Body><ns1:doGoogleSearch'+' xmlns:ns1="urn:GoogleSearch"'+' SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">'+'<key xsi:type="xsd:string">GOOGLEKEY</key> <q'+' xsi:type="xsd:string">'+search+'</q> <start'+' xsi:type="xsd:int">0</start> <maxResults'+' xsi:type="xsd:int">10</maxResults> <filter'+' xsi:type="xsd:boolean">true</filter> <restrict'+' xsi:type="xsd:string"></restrict> <safeSearch'+' xsi:type="xsd:boolean">false</safeSearch> <lr'+' xsi:type="xsd:string"></lr> <ie'+' xsi:type="xsd:string">latin1</ie> <oe'+' xsi:type="xsd:string">latin1</oe>'+'</ns1:doGoogleSearch>'+'</SOAP-ENV:Body></SOAP-ENV:Envelope>')

  Google使用的是SOAP介面,許多人認為SOAP存在需要值得謹慎考慮的問題。而REST也許是一個更好的模型,因為它能夠與當前的web架構、代理、緩衝等等進行協作。所以雖然我們能夠使用XML HTTP Request與soap通訊,在我們確實沒法控制服務端所所發生的一切之前還是盡量不要使用它。(感謝Dan Schmierer指出了我指令碼中的一個錯誤。)

  預設情況下這個對象只能回調同一台伺服器,而在一個安全要求降低的環境下(指通過file://訪問),IE能夠訪問任何的域,而Mozilla也那能夠實現,如果你提出請求,就會擷取適當的許可權。(子烏註:下面這句我不會翻譯。。。啥意思?"a google thread I can't get to offline!")

  腳註1:實際上許多“AJAX”應用程式幾乎不使用這個XML HTTP REQUEST對象,而是使用更老、但在大多數情況下更靈活的IFRAME執行遠程指令碼方法,但他們(“AJAX”應用程式)也能夠使用這個對象,而且應該養成AJAX是一種使用XML HTTP REQUEST建立的應用程式的觀念。



相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.