?? 掌握 ajax,第 2 部分 使用 javascript 和 ajax 發(fā)出異步請(qǐng)求.htm
字號(hào):
width="100%"><BR><IMG height=6 alt=""
src="掌握 Ajax,第 2 部分 使用 JavaScript 和 Ajax 發(fā)出異步請(qǐng)求.files/c.gif"
width=8 border=0></TD></TR></TBODY></TABLE>
<TABLE class=no-print cellSpacing=0 cellPadding=0 align=right>
<TBODY>
<TR align=right>
<TD><IMG height=4 alt=""
src="掌握 Ajax,第 2 部分 使用 JavaScript 和 Ajax 發(fā)出異步請(qǐng)求.files/c.gif"
width="100%"><BR>
<TABLE cellSpacing=0 cellPadding=0 border=0>
<TBODY>
<TR>
<TD vAlign=center><IMG height=16 alt=""
src="掌握 Ajax,第 2 部分 使用 JavaScript 和 Ajax 發(fā)出異步請(qǐng)求.files/u_bold.gif"
width=16 border=0><BR></TD>
<TD vAlign=top align=right><A class=fbox
href="http://www.ibm.com/developerworks/cn/xml/wa-ajaxintro2/#main"><B>回頁(yè)首</B></A></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE><BR><BR>
<P><A name=N102A0><SPAN class=atitle>用 XMLHttpRequest
發(fā)送請(qǐng)求</SPAN></A></P>
<P>得到請(qǐng)求對(duì)象之后就可以進(jìn)入請(qǐng)求/響應(yīng)循環(huán)了。記住,<CODE>XMLHttpRequest</CODE>
惟一的目的是讓您發(fā)送請(qǐng)求和接收響應(yīng)。其他一切都是 JavaScript、CSS
或頁(yè)面中其他代碼的工作:改變用戶界面、切換圖像、解釋服務(wù)器返回的數(shù)據(jù)。準(zhǔn)備好 <CODE>XMLHttpRequest</CODE>
之后,就可以向服務(wù)器發(fā)送請(qǐng)求了。</P>
<P><A name=N102B1><SPAN class=smalltitle>歡迎使用沙箱</SPAN></A></P>
<P>Ajax 采用一種沙箱安全模型。因此,Ajax 代碼(具體來(lái)說(shuō)就是 <CODE>XMLHttpRequest</CODE>
對(duì)象)只能對(duì)所在的同一個(gè)域發(fā)送請(qǐng)求。以后的文章中將進(jìn)一步介紹安全和
Ajax,現(xiàn)在只要知道在本地機(jī)器上運(yùn)行的代碼只能對(duì)本地機(jī)器上的服務(wù)器端腳本發(fā)送請(qǐng)求。如果讓 Ajax 代碼在
www.breakneckpizza.com 上運(yùn)行,則必須 www.breakneck.com 中運(yùn)行的腳本發(fā)送請(qǐng)求。</P>
<P><A name=N102BD><SPAN class=smalltitle>設(shè)置服務(wù)器 URL</SPAN></A></P>
<P>首先要確定連接的服務(wù)器的 URL。這并不是 Ajax 的特殊要求,但仍然是建立連接所必需的,顯然現(xiàn)在您應(yīng)該知道如何構(gòu)造 URL
了。多數(shù)應(yīng)用程序中都會(huì)結(jié)合一些靜態(tài)數(shù)據(jù)和用戶處理的表單中的數(shù)據(jù)來(lái)構(gòu)造該 URL。比如,<A
href="http://www.ibm.com/developerworks/cn/xml/wa-ajaxintro2/#code7">清單
7</A> 中的 JavaScript 代碼獲取電話號(hào)碼字段的值并用其構(gòu)造 URL。</P><BR><BR><A
name=code7><B>清單 7. 建立請(qǐng)求 URL</B></A><BR>
<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD class=code-outline><PRE class=displaycode>
<script language="javascript" type="text/javascript">
var request = false;
try {
request = new XMLHttpRequest();
} catch (trymicrosoft) {
try {
request = new ActiveXObject("Msxml2.XMLHTTP");
} catch (othermicrosoft) {
try {
request = new ActiveXObject("Microsoft.XMLHTTP");
} catch (failed) {
request = false;
}
}
}
if (!request)
alert("Error initializing XMLHttpRequest!");
function getCustomerInfo() {
<SPAN class=boldcode>var phone = document.getElementById("phone").value;
var url = "/cgi-local/lookupCustomer.php?phone=" + escape(phone);</SPAN>
}
</script>
</PRE></TD></TR></TBODY></TABLE><BR>
<P>這里沒(méi)有難懂的地方。首先,代碼創(chuàng)建了一個(gè)新變量 <CODE>phone</CODE>,并把 ID 為 “phone”
的表單字段的值賦給它。<A
href="http://www.ibm.com/developerworks/cn/xml/wa-ajaxintro2/#code8">清單
8</A> 展示了這個(gè)表單的 XHTML,其中可以看到 <CODE>phone</CODE> 字段及其 <CODE>id</CODE>
屬性。</P><BR><BR><A name=code8><B>清單 8. Break Neck Pizza
表單</B></A><BR>
<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD class=code-outline><PRE class=displaycode>
<body>
<p><img src="breakneck-logo_4c.gif" alt="Break Neck Pizza" /></p>
<form action="POST">
<p>Enter your phone number:
<SPAN class=boldcode><input type="text" size="14" name="phone" id="phone"
onChange="getCustomerInfo();" /></SPAN>
</p>
<p>Your order will be delivered to:</p>
<div id="address"></div>
<p>Type your order in here:</p>
<p><textarea name="order" rows="6" cols="50" id="order"></textarea></p>
<p><input type="submit" value="Order Pizza" id="submit" /></p>
</form>
</body>
</PRE></TD></TR></TBODY></TABLE><BR>
<P>還要注意,當(dāng)用戶輸入電話號(hào)碼或者改變電話號(hào)碼時(shí),將觸發(fā) <A
href="http://www.ibm.com/developerworks/cn/xml/wa-ajaxintro2/#code8">清單
8</A> 所示的 <CODE>getCustomerInfo()</CODE> 方法。該方法取得電話號(hào)碼并構(gòu)造存儲(chǔ)在
<CODE>url</CODE> 變量中的 URL 字符串。記住,由于 Ajax 代碼是沙箱型的,因而只能連接到同一個(gè)域,實(shí)際上 URL
中不需要域名。該例中的腳本名為 <CODE>/cgi-local/lookupCustomer.php</CODE>。最后,電話號(hào)碼作為
GET 參數(shù)附加到該腳本中:<CODE>"phone=" + escape(phone)</CODE>。</P>
<P>如果以前沒(méi)用見(jiàn)過(guò) <CODE>escape()</CODE>
方法,它用于轉(zhuǎn)義不能用明文正確發(fā)送的任何字符。比如,電話號(hào)碼中的空格將被轉(zhuǎn)換成字符 <CODE>%20</CODE>,從而能夠在 URL
中傳遞這些字符。</P>
<P>可以根據(jù)需要添加任意多個(gè)參數(shù)。比如,如果需要增加另一個(gè)參數(shù),只需要將其附加到 URL 中并用
“與”(<CODE>&</CODE>)字符分開(kāi) [第一個(gè)參數(shù)用問(wèn)號(hào)(<CODE>?</CODE>)和腳本名分開(kāi)]。</P>
<P><A name=N10323><SPAN class=smalltitle>打開(kāi)請(qǐng)求</SPAN></A></P>
<TABLE cellSpacing=0 cellPadding=0 width="45%" align=right
border=0><TBODY>
<TR>
<TD width=10><IMG height=1 alt=""
src="掌握 Ajax,第 2 部分 使用 JavaScript 和 Ajax 發(fā)出異步請(qǐng)求.files/c.gif"
width=10></TD>
<TD>
<TABLE cellSpacing=0 cellPadding=5 width="100%" border=1>
<TBODY>
<TR>
<TD bgColor=#eeeeee><A name=N1032C><B>open()
是打開(kāi)嗎?</B></A><BR>Internet 開(kāi)發(fā)人員對(duì) <CODE>open()</CODE>
方法到底做什么沒(méi)有達(dá)成一致。但它實(shí)際上并<I>不是</I> 打開(kāi)一個(gè)請(qǐng)求。如果監(jiān)控 XHTML/Ajax
頁(yè)面及其連接腳本之間的網(wǎng)絡(luò)和數(shù)據(jù)傳遞,當(dāng)調(diào)用 <CODE>open()</CODE>
方法時(shí)將看不到任何通信。不清楚為何選用了這個(gè)名字,但顯然不是一個(gè)好的選擇。
</TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE>
<P>有了要連接的 URL 后就可以配置請(qǐng)求了。可以用 <CODE>XMLHttpRequest</CODE> 對(duì)象的
<CODE>open()</CODE> 方法來(lái)完成。該方法有五個(gè)參數(shù):</P>
<UL>
<LI><I>request-type</I>:發(fā)送請(qǐng)求的類型。典型的值是 <CODE>GET</CODE> 或
<CODE>POST</CODE>,但也可以發(fā)送 <CODE>HEAD</CODE> 請(qǐng)求。
<LI><I>url</I>:要連接的 URL。
<LI><I>asynch</I>:如果希望使用異步連接則為 true,否則為 false。該參數(shù)是可選的,默認(rèn)為 true。
<LI><I>username</I>:如果需要身份驗(yàn)證,則可以在此指定用戶名。該可選參數(shù)沒(méi)有默認(rèn)值。
<LI><I>password</I>:如果需要身份驗(yàn)證,則可以在此指定口令。該可選參數(shù)沒(méi)有默認(rèn)值。 </LI></UL>
<P>通常使用其中的前三個(gè)參數(shù)。事實(shí)上,即使需要異步連接,也應(yīng)該指定第三個(gè)參數(shù)為
“true”。這是默認(rèn)值,但堅(jiān)持明確指定請(qǐng)求是異步的還是同步的更容易理解。</P>
<P>將這些結(jié)合起來(lái),通常會(huì)得到 <A
href="http://www.ibm.com/developerworks/cn/xml/wa-ajaxintro2/#code9">清單
9</A> 所示的一行代碼。</P><BR><BR><A name=code9><B>清單 9. 打開(kāi)請(qǐng)求</B></A><BR>
<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD class=code-outline><PRE class=displaycode>
function getCustomerInfo() {
var phone = document.getElementById("phone").value;
var url = "/cgi-local/lookupCustomer.php?phone=" + escape(phone);
<SPAN class=boldcode>request.open("GET", url, true);</SPAN>
}
</PRE></TD></TR></TBODY></TABLE><BR>
<P>一旦設(shè)置好了 URL,其他就簡(jiǎn)單了。多數(shù)請(qǐng)求使用 <CODE>GET</CODE> 就夠了(后面的文章中將看到需要使用
<CODE>POST</CODE> 的情況),再加上 URL,這就是使用 <CODE>open()</CODE>
方法需要的全部?jī)?nèi)容了。</P>
<P><A name=N10396><SPAN class=smalltitle>挑戰(zhàn)異步性</SPAN></A></P>
<P>本系列的后面一篇文章中,我將用很多時(shí)間編寫(xiě)和使用異步代碼,但是您應(yīng)該明白為什么 <CODE>open()</CODE>
的最后一個(gè)參數(shù)這么重要。在一般的請(qǐng)求/響應(yīng)模型中,比如 Web
1.0,客戶機(jī)(瀏覽器或者本地機(jī)器上運(yùn)行的代碼)向服務(wù)器發(fā)出請(qǐng)求。該請(qǐng)求是同步的,換句話說(shuō),客戶機(jī)等待服務(wù)器的響應(yīng)。當(dāng)客戶機(jī)等待的時(shí)候,至少會(huì)用某種形式通知您在等待:</P>
<UL>
<LI>沙漏(特別是 Windows 上)。
<LI>旋轉(zhuǎn)的皮球(通常在 Mac 機(jī)器上)。
<LI>應(yīng)用程序基本上凍結(jié)了,然后過(guò)一段時(shí)間光標(biāo)變化了。 </LI></UL>
<P>這正是 Web 應(yīng)用程序讓人感到笨拙或緩慢的原因 ——
缺乏真正的交互性。按下按鈕時(shí),應(yīng)用程序?qū)嶋H上變得不能使用,直到剛剛觸發(fā)的請(qǐng)求得到響應(yīng)。如果請(qǐng)求需要大量服務(wù)器處理,那么等待的時(shí)間可能很長(zhǎng)(至少在這個(gè)多處理器、DSL
沒(méi)有等待的世界中是如此)。</P>
<P>而異步請(qǐng)求<I>不</I> 等待服務(wù)器響應(yīng)。發(fā)送請(qǐng)求后應(yīng)用程序繼續(xù)運(yùn)行。用戶仍然可以在 Web
表單中輸入數(shù)據(jù),甚至離開(kāi)表單。沒(méi)有旋轉(zhuǎn)的皮球或者沙漏,應(yīng)用程序也沒(méi)有明顯的凍結(jié)。服務(wù)器悄悄地響應(yīng)請(qǐng)求,完成后告訴原來(lái)的請(qǐng)求者工作已經(jīng)結(jié)束(具體的辦法很快就會(huì)看到)。結(jié)果是,應(yīng)用程序感覺(jué)<I>不</I>
那么遲鈍或者緩慢,而是響應(yīng)迅速、交互性強(qiáng),感覺(jué)快多了。這僅僅是 Web 2.0 的一部分,但它是很重要的一部分。所有老套的 GUI
組件和 Web 設(shè)計(jì)范型都不能克服緩慢、同步的請(qǐng)求/響應(yīng)模型。</P>
<P><A name=N103BA><SPAN class=smalltitle>發(fā)送請(qǐng)求</SPAN></A></P>
<P>一旦用 <CODE>open()</CODE> 配置好之后,就可以發(fā)送請(qǐng)求了。幸運(yùn)的是,發(fā)送請(qǐng)求的方法的名稱要比
<CODE>open()</CODE> 適當(dāng),它就是 <CODE>send()</CODE>。</P>
<P><CODE>send()</CODE> 只有一個(gè)參數(shù),就是要發(fā)送的內(nèi)容。但是在考慮這個(gè)方法之前,回想一下前面已經(jīng)通過(guò) URL
本身發(fā)送過(guò)數(shù)據(jù)了:</P>
<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD class=code-outline><PRE class=displaycode>var url = "/cgi-local/lookupCustomer.php?<SPAN class=boldcode>phone=" + escape(phone);</SPAN>
</PRE></TD></TR></TBODY></TABLE><BR>
<P>雖然可以使用 <CODE>send()</CODE> 發(fā)送數(shù)據(jù),但也能通過(guò) URL
本身發(fā)送數(shù)據(jù)。事實(shí)上,<CODE>GET</CODE> 請(qǐng)求(在典型的 Ajax 應(yīng)用中大約占 80%)中,用 URL
發(fā)送數(shù)據(jù)要容易得多。如果需要發(fā)送安全信息或 XML,可能要考慮使用 <CODE>send()</CODE>
發(fā)送內(nèi)容(本系列的后續(xù)文章中將討論安全數(shù)據(jù)和 XML 消息)。如果不需要通過(guò) <CODE>send()</CODE>
傳遞數(shù)據(jù),則只要傳遞 <CODE>null</CODE> 作為該方法的參數(shù)即可。因此您會(huì)發(fā)現(xiàn)在本文中的例子中只需要這樣發(fā)送請(qǐng)求(參見(jiàn)
<A
href="http://www.ibm.com/developerworks/cn/xml/wa-ajaxintro2/#code10">清單
10</A>)。</P><BR><BR><A name=code10><B>清單 10. 發(fā)送請(qǐng)求</B></A><BR>
<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD class=code-outline><PRE class=displaycode>
function getCustomerInfo() {
var phone = document.getElementById("phone").value;
var url = "/cgi-local/lookupCustomer.php?phone=" + escape(phone);
request.open("GET", url, true);
<SPAN class=boldcode>request.send(null);</SPAN>
}
</PRE></TD></TR></TBODY></TABLE><BR>
<P><A name=N10404><SPAN class=smalltitle>指定回調(diào)方法</SPAN></A></P>
<P>現(xiàn)在我們所做的只有很少一點(diǎn)是新的、革
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -