国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > JavaScript > 正文

Javascript 基礎---Ajax入門必看

2019-11-20 09:33:16
字體:
來源:轉載
供稿:網(wǎng)友

Ajax 是現(xiàn)代Web 應用程序開發(fā)的一項關鍵工具。它讓你能向服務器異步發(fā)送和接收數(shù)據(jù),然后用 Javascript 解析。 Ajax 是 Asynchronous JavaScript and XML (異步JavaScript 與XML)的縮寫。

Ajax 核心規(guī)范的名稱繼承于用來建立和發(fā)起請求的 Javascript 對象:XMLHttpRequest 。這個規(guī)范有兩個等級。所有主流瀏覽器都實現(xiàn)了第一級,它代表了基礎級別的功能。第二級擴展了最初的規(guī)范,納入了額外的事件和一些功能來讓它更容易與 form 元素協(xié)作,并且支持一些相關規(guī)范。 

1. Ajax起步

Ajax 的關鍵在于 XMLHttpRequest 對象,而理解這個對象的方法是看個例子。下面代碼展示了 XMLHttpRequest 對象的簡單用法:

<!DOCTYPE html><html lang="en"><head>  <meta charset="UTF-8">  <title>Example</title></head><body><div>  <button>apples</button>  <button>cherries</button>  <button>bananas</button></div><div id="target">  Press a button</div><script type="application/javascript"> var buttons = document.getElementsByTagName("button");  for(var i=0; i<buttons.length; i++){    buttons[i].onclick = handleButtonPress;  }  //腳本會調(diào)用此函數(shù)以響應 button 控件的 click 事件  function handleButtonPress(e){    //創(chuàng)建一個新的 XMLHttpRequest 對象    var httpRequest = new XMLHttpRequest();    //給 onreadystatechange 事件設置一個事件處理器    httpRequest.onreadystatechange = handleResponse;    //使用 open 方法來指定 HTTP 方法和需要請求的 URL (即告訴 httpRequest 對象你想要做的事)    httpRequest.open("GET", e.target.innerHTML+".html");    //這里沒有向服務器發(fā)送任何數(shù)據(jù),所以 send 方法無參數(shù)可用    httpRequest.send();  }  //處理響應  //一旦腳本調(diào)用了 send 方法,瀏覽器就會在后臺發(fā)送請求到服務器。因為請求是在后臺處理的,所以Ajax 依靠事件來通知這個請求的進展情況。  function handleResponse(e){    //當 onreadystatechange 事件被觸發(fā)后,瀏覽器會把一個 Event 對象傳遞給指定的處理函數(shù),target 屬性則會被設為與此事件關聯(lián)的XMLHttpRequest    if(e.target.readyState == XMLHttpRequest.DONE && e.target.status == 200){ //請求成功      document.getElementById("target").innerHTML = e.target.responseText; //顯示被請求文檔的內(nèi)容    }  }</script></body></html>

三個額外的文檔非常簡單:

<!DOCTYPE html><html lang="en"><head>  <meta charset="UTF-8">  <title>Apples</title>  <style>    img { float:left;padding:2px;margin:5px;border: medium double black;background-color: lightgrey; width: 100px;height: 100px;}  </style></head><body><p>  <img src="../img/show-page/img_apples.jpg"/>  Page for apples.</p></body></html>

效果如下圖所示:

隨著用戶點擊各個水果按鈕,瀏覽器會異步執(zhí)行并取回所請求的文檔,而主文檔不會被重新加載。這就是典型的 Ajax 行為。

 2. 使用 Ajax 事件

建立和探索一個簡單的示例之后,可以開始深入了解 XMLHttpRequest 對象支持的功能,以及如何在請求中使用它們了。起點就是第二級規(guī)范里定義的那些額外事件:

這些事件大多數(shù)會在請求的某一特定時間點上觸發(fā)。 readystatechange 和 progress 這兩個事件是例外,它們可以多次觸發(fā)以提供進度更新。

調(diào)度這些事件時,瀏覽器會對 readystatechange 事件使用常規(guī)的 Event 對象,對其他事件則使用 ProgressEvent 對象。 ProgressEvent 對象定義了 Event 對象的所有成員,并增加了下圖中介紹的這些成員:

下面代碼展示了如何使用這些事件:

<!DOCTYPE html><html lang="en"><head>  <meta charset="UTF-8">  <title>Example</title>  <style>    table {margin: 10px;border-collapse: collapse; float: left;}    div{margin: 10px;}    td,th{padding: 4px;}  </style></head><body><div>  <button>apples</button>  <button>cherries</button>  <button>bananas</button></div><table id="events" border="1"></table><div id="target">  Press a button</div><script type="application/javascript">  var buttons = document.getElementsByTagName("button");  for(var i=0; i<buttons.length; i++){    buttons[i].onclick = handleButtonPress;  }    var httpRequest;  function handleButtonPress(e){    clearEventDetails();    httpRequest = new XMLHttpRequest();    httpRequest.onreadystatechange = handleResponse;    httpRequest.onerror = handleError;    httpRequest.onload = handleLoad;;    httpRequest.onloadend = handleLoadEnd;    httpRequest.onloadstart = handleLoadStart;;    httpRequest.onprogress = handleProgress;    httpRequest.open("GET", e.target.innerHTML+".html");    httpRequest.send();  }  function handleResponse(e){    displayEventDetails("readystate("+httpRequest.readyState+")")    if(e.target.readyState == XMLHttpRequest.DONE && e.target.status == 200){      document.getElementById("target").innerHTML = e.target.responseText;    }  }  function handleError(e){ displayEventDetails("error",e);}  function handleLoad(e){ displayEventDetails("load",e);}  function handleLoadEnd(e){ displayEventDetails("loadend",e);}  function handleLoadStart(e){ displayEventDetails("loadstart",e);}  function handleProgress(e){ displayEventDetails("progress",e);}  function clearEventDetails(){    document.getElementById("events").innerHTML = "<tr><th>Event</th><th>lengthComputable</th><th>loaded</th><th>total</th>";  }  function displayEventDetails(eventName,e){    if(e){      document.getElementById("events").innerHTML          +="<tr><td>"+eventName+"</td><td>"+ e.lengthComputable+"</td><td>"+ e.loaded+"</td><td>"+ e.total+"</td></tr>";    }else {      document.getElementById("events").innerHTML += "<tr><td>"+eventName+"</td><td>NA</td><td>NA</td><td>NA</td></tr>";    }  }</script></body></html>

這是之前示例的一種變型,為一些事件注冊了處理函數(shù),并在一個 table 元素里為處理的每個事件都創(chuàng)建了一條記錄。從下圖中可以看到 Firefox 瀏覽器是如何觸發(fā)這些事件的。

3. 處理錯誤

使用 Ajax 時必須留心兩類錯誤。它們之間的區(qū)別源于視角不同。

第一類錯誤是從 XMLHttpRequest 對象的角度看到的問題:某些因素阻止了請求發(fā)送到服務器。例如 DNS 無法解析主機名,連接請求被拒絕,或者URL無效。

第二類問題是從應用程序的角度看到的問題,而非 XMLHttpRequest 對象。它們發(fā)生于請求成功發(fā)送至服務器,服務器接收請求、進行處理并生成響應,但該響應并不指向你期望的內(nèi)容。例如,如果請求的URL 不存在,這類問題就會發(fā)生。

有三種方式可以處理這些錯誤,如下面代碼所示:

3.1 處理設置錯誤

需要處理的第一類問題是向 XMLHttpResquest 對象傳遞了錯誤的數(shù)據(jù),比如格式不正確的 URL 。它們極其容易發(fā)生在生成基于用戶輸入的URL 時。為了模擬這類問題,上面文檔中有添加一個標簽 Bad URL (錯誤的URL)的button 。按下這個按鈕會以以下形式調(diào)用 open 方法:

httpRequest.open("GET","http://")

 這是一種會阻止請求執(zhí)行的錯誤,而 XMLHttpRequest 對象會發(fā)生這類事件時拋出一個錯誤。這就意味著需要用一條 try...catch 語句來圍住設置請求的代碼,就像這樣:

 

try{      ...      httpRequest.open("GET","http://")      ...      httpRequest.send();    }catch(error){      displayErrorMsg("try/catch",error.message)    }

 catch 子句讓你有機會從錯誤中恢復??梢赃x擇提示用戶輸入一個值,也可以回退至默認的URL ,或是簡單地丟棄這個請求。 在這個例子中,僅僅調(diào)用了 displayErrorMsg 函數(shù)來顯示錯誤消息。

3.2 處理請求錯誤

第二類錯誤發(fā)生在請求已生成,但其他方面出錯時。為了模擬這類問題,在示例中添加了一個標簽為 Bad Host (錯誤主機)的按鈕。當這個按鈕被按下后,就會調(diào)用 open 方法訪問一個不可用的 URL:

httpRequest.open("GET",http://www.ycdoitt.com/nopage.html)

這個URL 存在兩個問題。第一個問題是主機名不能被 DNS 解析,因此瀏覽器無法生成服務器連接。這個問題知道 XMLHttpRequest 對象開始生成請求時才會變得明顯,因此它會以兩種方式發(fā)出錯誤信號。如果你注冊了一個 error 事件的監(jiān)聽器,瀏覽器就會向你的監(jiān)聽函數(shù)發(fā)送一個 Event 對象。以下是示例中使用的函數(shù):

function handleError(e){    displayErrorMsg("Error event",httpRequest.status + httpRequest.statusText);  }

 當這類錯誤發(fā)生時,能從 XMLHttpRequest 對象獲得何種程度的信息取決于瀏覽器,遺憾的是大多數(shù)情況下,會得到的值為 0的 status和空白的 statusText 值。

第二個問題是URL和生成請求的具有不同的來源,在默認情況下這是不允許的。你通常只能向載入腳本的同源URL發(fā)送Ajax請求。瀏覽器報告這個問題時可能會拋出 Error 或者觸發(fā)error事件,不同瀏覽器的處理方法不盡相同。不同瀏覽器還會在不同的時點檢查來源,這就意味著不一定總是能看到瀏覽器對同一問題突出顯示??梢允褂每缯举Y源規(guī)范(CORS,Cross-Origin Resource Sharing)來繞過同源限制。

3.3 處理應用程序錯誤

最后一類錯誤發(fā)生于請求成功完成(從XMLHttpRequest對象的角度看),但沒有返回你想要的數(shù)據(jù)時。為了制造這類問題,在上面示例中添加一個說明標簽為 cucumber 的 button 。按下這個按鈕會生成類似于 apples、cherries 和 bananas 按鈕那樣的請求URL,但是在服務器上不存在 cucumber.html 這個文檔。

這一過程本身沒有錯誤(因為請求已完成),需要根據(jù) status屬性來確定發(fā)生了什么。當請求某個存在的文檔時,會獲得404這個狀態(tài)碼,它的意思是服務器無法找到請求的文檔。可以看到示例是如何處理200(意思是OK)以外的狀態(tài)碼的:

if(httpRequest.status == 200){        target.innerHTML = httpRequest.responseText;      }else{        document.getElementById("statusmsg").innerHTML            = "Status:" + httpRequest.status +" "+ httpRequest.statusText;      }

在這個例子中,只是簡單的顯示了status和statusText的值。而在真正的應用程序里,需要以一種有用且有意義的方式進行恢復(比如顯示備用內(nèi)容或警告用戶有問題,具體看哪種更適合應用程序)。

 4. 獲取和設置標頭

使用XMLHttpRequest對象,可以設置發(fā)送給服務器的請求標頭(Header)和讀取服務器響應里的標頭。

 

4.1 覆蓋請求的HTTP方法

通常不需要添加或修改Ajax請求里的標頭。瀏覽器知道需要發(fā)送些什么,服務器也知道如何進行響應。不過,有幾種情況例外。第一種是 X-HTTP-Method-Override 標頭。

HTTP標準通常被用于在互聯(lián)網(wǎng)上請求和傳輸HTML文檔,它定義了許多方法。大多數(shù)人都知道GET和POST,因為它們的使用最為廣泛。不過還存在其他一些方法(包括PUT和DELETE),這些HTTP方法用來給向服務器請求的URL賦予意義,而且這種用法正在呈現(xiàn)上升趨勢。舉個例子,假如想查看某條用戶記錄,可以生成這樣一個請求:

httpRequest.open("GET","http://myserver/records/freeman/adam");

 這里只展示了HTTP方法和請求的URL。要使這個請求能順利工作,服務器端必須由應用程序能理解這個請求,并將它轉變成一段合適的數(shù)據(jù)以發(fā)送回服務器。如果想刪除數(shù)據(jù),可以這么寫:

httpRequest.open("DELETE","http://myserver/records/freeman/adam");

此處的關鍵在于通過HTTP方法表達出你想讓服務器做什么,而不是把它用某種方式編碼進URL。

以這種方式使用HTTP方法的問題在于:許多主流的Web技術只支持GET和POST,而且不少防火墻只允許GET和POST請求通過。有一種慣用的做法可以規(guī)避這個限制,就是使用 X-HTTP-Method-Override標頭來指定想要使用的HTTP方法,但形式上市在發(fā)送一個POST請求。代碼演示如下:

<!DOCTYPE html><html lang="en"><head>  <meta charset="UTF-8">  <title>Example</title></head><body><div>  <button>apples</button>  <button>cherries</button>  <button>bananas</button></div><div id="target">Press a button</div><script>  var buttons = document.getElementsByTagName("button");  for(var i = 0; i < buttons.length; i++){    buttons[i].onclick = handleButtonPress;  }  var httpRequest;  function handleButtonPress(e){    httpRequest = new XMLHttpRequest();    httpRequest.onreadystatechange = handleResponse;    httpRequest.open("GET", e.target.innerHTML+".html");    httpRequest.setRequestHeader("X-HTTP-Method-Override","DELETE");    httpRequest.send();  }  function handleError(e){    displayErrorMsg("Error event",httpRequest.status+httpRequest.statusText);  }  function handleResponse(){    if(httpRequest.readyState == 4 && httpRequest.status == 200){      document.getElementById("target").innerHTML = httpRequest.responseText;    }  }</script></body></html>

在這個例子中,有使用XMLHttpRequest對象上的setRequestHeader方法來表明想讓這個請求以HTTP DELETE方法的形式進行處理。請注意我在調(diào)用open方法之后才設置了這個標頭。如果試圖在open方法之前使用setRequestHeader方法,XMLHttpRequest對象就會拋出一個錯誤。

PS:覆蓋HTTP需要服務器端的Web應用程序框架能理解X-HTTP-Method-Override這個慣例,并且你的服務器端應用程序要設置成能尋找和理解那些用的較少的HTTP方法。

 

4.2 禁用內(nèi)容緩存

第二個可以添加到Ajax請求上的有用標頭是Cache-Control,它在編寫和調(diào)試腳本時尤其有用。一些瀏覽器會緩存通過Ajax請求所獲得的內(nèi)容,在瀏覽會話期間不會再請求它。對在前面的例子而言,意味著 apples.html、cherries.html和bananas.html 上的改動不會立即反映到瀏覽器中。下面代碼展示了可以如何設置標頭來避免這一點:

httpRequest = new XMLHttpRequest();    httpRequest.onreadystatechange = handleResponse;    httpRequest.open("GET", e.target.innerHTML+".html");    httpRequest.setRequestHeader("Cache-Control","no-cache");    httpRequest.send();

設置標頭的方式和之前的例子一樣,但這次用到的標頭是 Cache-Control,而想要的值是 no-cache。放置這條語句后,如果通過Ajax請求的內(nèi)容發(fā)生了改變,就會在下一次請求文檔時體現(xiàn)出來。

 

4.3 讀取響應標頭

可以通過 getResponseHeader 和 getAllResponseHeaders 方法來讀取服務器響應某個Ajax請求時發(fā)送的HTTP標頭。在大多數(shù)情況下,你不需要關心標頭里有什么,因為它們是瀏覽器和服務器之間交互事務的組成部分。下面代碼展示了如何使用這個屬性:

<!DOCTYPE html><html lang="en"><head>  <meta charset="UTF-8">  <meta content="width=device-width,user-scalable=no" name="viewport" />  <meta name="author" content="葉超Luka" />  <meta name="description" content="A simple example" />  <title>Example</title>  <link href="../img/ycdoit.ico" type="image/x-icon" rel="shortcut icon" />  <style>    #allheaders,#ctheader{border: medium solid black;padding: 2px;margin: 2px;}  </style></head><body><div>  <button>apples</button>  <button>cherries</button>  <button>bananas</button></div><div id="ctheader"></div><div id="allheaders"></div><div id="target">Press a button</div><script>  var buttons = document.getElementsByTagName("button");  for(var i = 0; i < buttons.length; i++){    buttons[i].onclick = handleButtonPress;  }  var httpRequest;  function handleButtonPress(e){    httpRequest = new XMLHttpRequest();    httpRequest.onreadystatechange = handleResponse;    httpRequest.open("GET", e.target.innerHTML+".html");    httpRequest.setRequestHeader("Cache-Control","no-cache");    httpRequest.send();  }  function handleResponse(){    if(httpRequest.readyState==2){      document.getElementById("allheaders").innerHTML = httpRequest.getAllResponseHeaders();      document.getElementById("ctheader").innerHTML = httpRequest.getResponseHeader("Content-Type");    }else if(httpRequest.readyState == 4 && httpRequest.status == 200){      document.getElementById("target").innerHTML = httpRequest.responseText;    }  }</script></body></html>

效果圖如下:

根據(jù)此圖可以看出開發(fā)服務器正在運行的Web服務器軟件是 IntelliJ IDEA 15.0.4,最后修改 apples.html 文檔的時間是6月27日(但屏幕截圖是7月5日)。

 

發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 双流县| 太仆寺旗| 易门县| 峨山| 桐城市| 定南县| 泰来县| 金山区| 和田县| 长武县| 义乌市| 曲松县| 盐山县| 龙口市| 巴塘县| 陆川县| 雷山县| 阳谷县| 灌云县| 静乐县| 冕宁县| 庆安县| 南开区| 文昌市| 石渠县| 杭州市| 蒲江县| 兴和县| 宜宾县| 汾阳市| 吉水县| 临桂县| 都匀市| 白山市| 濮阳县| 清原| 阳江市| 宽甸| 牙克石市| 汶川县| 措美县|