1. 程式人生 > >AJAX非同步的 JavaScript

AJAX非同步的 JavaScript

什麼是AJAX:

AJAX = Asynchronous JavaScript and XML(非同步的 JavaScript 和 XML)。

AJAX 不是新的程式語言,而是一種使用現有標準的新方法。

AJAX 是與伺服器交換資料並更新部分網頁的藝術,在不重新載入整個頁面的情況下。

AJAX 是一種在無需重新載入整個網頁的情況下,能夠更新部分網頁的技術。

AJAX 是一種用於建立快速動態網頁的技術。

通過在後臺與伺服器進行少量資料交換,AJAX 可以使網頁實現非同步更新。這意味著可以在不重新載入整個網頁的情況下,對網頁的某部分進行更新。

傳統的網頁(不使用 AJAX)如果需要更新內容,必需過載整個網頁面。

有很多使用 AJAX 的應用程式案例:新浪微博、Google 地圖、開心網等等。

Google Suggest

在 2005 年,Google 通過其 Google Suggest 使 AJAX 變得流行起來。

Google Suggest 使用 AJAX 創造出動態性極強的 web 介面:當您在谷歌的搜尋框輸入關鍵字時,JavaScript 會把這些字元傳送到伺服器,然後伺服器會返回一個搜尋建議的列表。

 

建立 XMLHttpRequest 物件

所有現代瀏覽器(IE7+、Firefox、Chrome、Safari 以及 Opera)均內建 XMLHttpRequest 物件。

建立 XMLHttpRequest 物件的語法:

variable=new XMLHttpRequest();

老版本的 Internet Explorer (IE5 和 IE6)使用 ActiveX 物件:

variable=new ActiveXObject("Microsoft.XMLHTTP");

為了應對所有的現代瀏覽器,包括 IE5 和 IE6,請檢查瀏覽器是否支援 XMLHttpRequest 物件。如果支援,則建立 XMLHttpRequest 物件。如果不支援,則建立 ActiveXObject :

var xmlhttp;
if (window.XMLHttpRequest)
  {// code for IE7+, Firefox, Chrome, Opera, Safari
  xmlhttp=new XMLHttpRequest();
  }
else
  {// code for IE6, IE5
  xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
  }

AJAX - 向伺服器傳送請求

XMLHttpRequest 物件用於和伺服器交換資料。

向伺服器傳送請求

如需將請求傳送到伺服器,我們使用 XMLHttpRequest 物件的 open() 和 send() 方法:

xmlhttp.open("GET","test1.txt",true);
xmlhttp.send();
方法 描述
open(method,url,async)

規定請求的型別、URL 以及是否非同步處理請求。

  • method:請求的型別;GET 或 POST
  • url:檔案在伺服器上的位置
  • async:true(非同步)或 false(同步)
send(string)

將請求傳送到伺服器。

  • string:僅用於 POST 請求

GET 還是 POST?

與 POST 相比,GET 更簡單也更快,並且在大部分情況下都能用。

然而,在以下情況中,請使用 POST 請求:

  • 無法使用快取檔案(更新伺服器上的檔案或資料庫)
  • 向伺服器傳送大量資料(POST 沒有資料量限制)
  • 傳送包含未知字元的使用者輸入時,POST 比 GET 更穩定也更可靠

GET 請求

一個簡單的 GET 請求:

為了避免這種情況,請向 URL 新增一個唯一的 ID:

xmlhttp.open("GET","demo_get.asp?t=" + Math.random(),true);
xmlhttp.send();

如果您希望通過 GET 方法傳送資訊,請向 URL 新增資訊:

xmlhttp.open("GET","demo_get2.asp?fname=Bill&lname=Gates",true);
xmlhttp.send();

POST 請求

一個簡單 POST 請求:

xmlhttp.open("POST","demo_post.asp",true);
xmlhttp.send();

如果需要像 HTML 表單那樣 POST 資料,請使用 setRequestHeader() 來新增 HTTP 頭。然後在 send() 方法中規定您希望傳送的資料:

xmlhttp.open("POST","ajax_test.asp",true);
xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xmlhttp.send("fname=Bill&lname=Gates");
 
 
方法 描述
setRequestHeader(header,value)

向請求新增 HTTP 頭。

  • header: 規定頭的名稱
  • value: 規定頭的值

非同步 - True 或 False?

AJAX 指的是非同步 JavaScript 和 XML(Asynchronous JavaScript and XML)。

XMLHttpRequest 物件如果要用於 AJAX 的話,其 open() 方法的 async 引數必須設定為 true:

xmlhttp.open("GET","ajax_test.asp",true);

對於 web 開發人員來說,傳送非同步請求是一個巨大的進步。很多在伺服器執行的任務都相當費時。AJAX 出現之前,這可能會引起應用程式掛起或停止。

通過 AJAX,JavaScript 無需等待伺服器的響應,而是:

  • 在等待伺服器響應時執行其他指令碼
  • 當響應就緒後對響應進行處理

Async = true

當使用 async=true 時,請規定在響應處於 onreadystatechange 事件中的就緒狀態時執行的函式:

xmlhttp.onreadystatechange=function()
  {
  if (xmlhttp.readyState==4 && xmlhttp.status==200)
    {
    document.getElementById("myDiv").innerHTML=xmlhttp.responseText;
    }
  }
xmlhttp.open("GET","test1.txt",true);
xmlhttp.send();

伺服器響應

如需獲得來自伺服器的響應,請使用 XMLHttpRequest 物件的 responseText 或 responseXML 屬性。

屬性 描述
responseText 獲得字串形式的響應資料。
responseXML 獲得 XML 形式的響應資料。

responseText 屬性

如果來自伺服器的響應並非 XML,請使用 responseText 屬性。

responseText 屬性返回字串形式的響應,因此您可以這樣使用:

document.getElementById("myDiv").innerHTML=xmlhttp.responseText;

responseXML 屬性

如果來自伺服器的響應是 XML,而且需要作為 XML 物件進行解析,請使用 responseXML 屬性:

請求 books.xml 檔案,並解析響應:

xmlDoc=xmlhttp.responseXML;
txt="";
x=xmlDoc.getElementsByTagName("ARTIST");
for (i=0;i<x.length;i++)
  {
  txt=txt + x[i].childNodes[0].nodeValue + "<br />";
  }
document.getElementById("myDiv").innerHTML=txt;
 
 

AJAX - onreadystatechange 事件

onreadystatechange 事件

當請求被髮送到伺服器時,我們需要執行一些基於響應的任務。

每當 readyState 改變時,就會觸發 onreadystatechange 事件。

readyState 屬性存有 XMLHttpRequest 的狀態資訊。

下面是 XMLHttpRequest 物件的三個重要的屬性:

屬性 描述
onreadystatechange 儲存函式(或函式名),每當 readyState 屬性改變時,就會呼叫該函式。
readyState

存有 XMLHttpRequest 的狀態。從 0 到 4 發生變化。

  • 0: 請求未初始化
  • 1: 伺服器連線已建立
  • 2: 請求已接收
  • 3: 請求處理中
  • 4: 請求已完成,且響應已就緒
status

200: "OK"

404: 未找到頁面

在 onreadystatechange 事件中,我們規定當伺服器響應已做好被處理的準備時所執行的任務。

當 readyState 等於 4 且狀態為 200 時,表示響應已就緒:

xmlhttp.onreadystatechange=function()
  {
  if (xmlhttp.readyState==4 && xmlhttp.status==200)
    {
    document.getElementById("myDiv").innerHTML=xmlhttp.responseText;
    }
  }

註釋:onreadystatechange 事件被觸發 5 次(0 - 4),對應著 readyState 的每個變化。

使用 Callback 函式

callback 函式是一種以引數形式傳遞給另一個函式的函式。

如果您的網站上存在多個 AJAX 任務,那麼您應該為建立 XMLHttpRequest 物件編寫一個標準的函式,併為每個 AJAX 任務呼叫該函式。

該函式呼叫應該包含 URL 以及發生 onreadystatechange 事件時執行的任務(每次呼叫可能不盡相同):

function myFunction()
{
loadXMLDoc("ajax_info.txt",function()
  {
  if (xmlhttp.readyState==4 && xmlhttp.status==200)
    {
    document.getElementById("myDiv").innerHTML=xmlhttp.responseText;
    }
  });
}

AJAX ASP/PHP 例項

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script>
function showHint(str)
{
  var xmlhttp;
  if (str.length==0)
  { 
    document.getElementById("txtHint").innerHTML="";
    return;
  }
  if (window.XMLHttpRequest)
  {
    // IE7+, Firefox, Chrome, Opera, Safari 瀏覽器執行程式碼
    xmlhttp=new XMLHttpRequest();
  }
  else
  {
    // IE6, IE5 瀏覽器執行程式碼
    xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
  }
  xmlhttp.onreadystatechange=function()
  {
    if (xmlhttp.readyState==4 && xmlhttp.status==200)
    {
      document.getElementById("txtHint").innerHTML=xmlhttp.responseText;
    }
  }
  xmlhttp.open("GET","/try/ajax/gethint.php?q="+str,true);
  xmlhttp.send();
}
</script>
</head>
<body>

<h3>在輸入框中嘗試輸入字母 a:</h3>
<form action=""> 
輸入姓名: <input type="text" id="txt1" onkeyup="showHint(this.value)" />
</form>
<p>提示資訊: <span id="txtHint"></span></p> 

</body>
</html>

在輸入框中嘗試輸入字母 a:

輸入姓名:

提示資訊:

 

AJAX 伺服器頁面 - ASP 和 PHP

由上面的 JavaScript 呼叫的伺服器頁面是 ASP 檔案,名為 "gethint.asp"。

下面,我們建立了兩個版本的伺服器檔案,一個用 ASP 編寫,另一個用 PHP 編寫。

ASP 檔案

"gethint.asp" 中的原始碼會檢查一個名字陣列,然後向瀏覽器返回相應的名字:

<%
response.expires=-1
dim a(30)
'Fill up array with names
a(1)="Anna"
a(2)="Brittany"
a(3)="Cinderella"
a(4)="Diana"
a(5)="Eva"
a(6)="Fiona"
a(7)="Gunda"
a(8)="Hege"
a(9)="Inga"
a(10)="Johanna"
a(11)="Kitty"
a(12)="Linda"
a(13)="Nina"
a(14)="Ophelia"
a(15)="Petunia"
a(16)="Amanda"
a(17)="Raquel"
a(18)="Cindy"
a(19)="Doris"
a(20)="Eve"
a(21)="Evita"
a(22)="Sunniva"
a(23)="Tove"
a(24)="Unni"
a(25)="Violet"
a(26)="Liza"
a(27)="Elizabeth"
a(28)="Ellen"
a(29)="Wenche"
a(30)="Vicky"

'get the q parameter from URL
q=ucase(request.querystring("q"))

'lookup all hints from array if length of q>0
if len(q)>0 then
  hint=""
  for i=1 to 30
    if q=ucase(mid(a(i),1,len(q))) then
      if hint="" then
        hint=a(i)
      else
        hint=hint & " , " & a(i)
      end if
    end if
  next
end if

'Output "no suggestion" if no hint were found
'or output the correct values
if hint="" then
  response.write("no suggestion")
else
  response.write(hint)
end if
%>

 

 
 

PHP 檔案

下面的程式碼用 PHP 編寫,與上面的 ASP 程式碼作用是一樣的。

<?php
// Fill up array with names
$a[]="Anna";
$a[]="Brittany";
$a[]="Cinderella";
$a[]="Diana";
$a[]="Eva";
$a[]="Fiona";
$a[]="Gunda";
$a[]="Hege";
$a[]="Inga";
$a[]="Johanna";
$a[]="Kitty";
$a[]="Linda";
$a[]="Nina";
$a[]="Ophelia";
$a[]="Petunia";
$a[]="Amanda";
$a[]="Raquel";
$a[]="Cindy";
$a[]="Doris";
$a[]="Eve";
$a[]="Evita";
$a[]="Sunniva";
$a[]="Tove";
$a[]="Unni";
$a[]="Violet";
$a[]="Liza";
$a[]="Elizabeth";
$a[]="Ellen";
$a[]="Wenche";
$a[]="Vicky";

//get the q parameter from URL
$q=$_GET["q"];

//lookup all hints from array if length of q>0
if (strlen($q) > 0)
{
  $hint="";
  for($i=0; $i<count($a); $i++)
  {
    if (strtolower($q)==strtolower(substr($a[$i],0,strlen($q))))
    {
      if ($hint=="")
      {
        $hint=$a[$i];
      }
      else
      {
        $hint=$hint." , ".$a[$i];
      }
    }
  }
}

// Set output to "no suggestion" if no hint were found
// or to the correct values
if ($hint == "")
{
  $response="no suggestion";
}
else
{
  $response=$hint;
}

//output the response
echo $response;
?>