詳解XMLHttpRequest(一)同步請(qǐng)求和異步請(qǐng)求
XMLHttpRequest 讓發(fā)送一個(gè)HTTP請(qǐng)求變得非常容易。你只需要簡(jiǎn)單的創(chuàng)建一個(gè)請(qǐng)求對(duì)象實(shí)例,打開一個(gè)URL,然后發(fā)送這個(gè)請(qǐng)求。當(dāng)傳輸完畢后,結(jié)果的HTTP狀態(tài)以及返回的響應(yīng)內(nèi)容也可以從請(qǐng)求對(duì)象中獲取。
通過XMLHttpRequest生成的請(qǐng)求可以有兩種方式來獲取數(shù)據(jù),異步模式或同步模式。請(qǐng)求的類型是由這個(gè)XMLHttpRequest對(duì)象的open()方法的第三個(gè)參數(shù)async的值決定的。如果該參數(shù)的值為false,則該XMLHttpRequest請(qǐng)求以同步模式進(jìn)行,否則該過程將以異步模式完成。
兩種通信模式:同步和異步請(qǐng)求:
同步請(qǐng)求
主線程中的同步請(qǐng)求會(huì)阻塞頁面,由于對(duì)用戶體驗(yàn)的糟糕效果,部分最新瀏覽器在主線程上的同步請(qǐng)求已經(jīng)被棄用。在極少數(shù)情況下,使用同步模式的XMLHttpRequests會(huì)比使用異步模式更適合。
1.在Worker中使用XMLHttpRequest時(shí),同步請(qǐng)求比異步請(qǐng)求更適合。
主頁中代碼:
<script type="text/javascript"> var oMyWorker = new Worker("myTask.js"); oMyWorker.onmessage = function(oEvent) { alert("Worker said: " + oEvent.data); }; oMyWorker.postMessage("Hello"); </script> myFile.txt ( XMLHttpRequest對(duì)象同步請(qǐng)求的文件): Hello World!!
包含了Worker代碼:myTask.js
self.onmessage = function (oEvent) { if (oEvent.data === "Hello") { var oReq = new XMLHttpRequest(); oReq.open("GET", "myFile.txt", false); // 同步請(qǐng)求 oReq.send(null); self.postMessage(oReq.responseText); } };
注意: 由于使用了Worker,所以該請(qǐng)求實(shí)際上也是異步的.
可以使用類似的方法,讓腳本在后臺(tái)與服務(wù)器交互,預(yù)加載某些內(nèi)容.查看使用web workers了解更多詳情
2.不得不使用同步請(qǐng)求的情況
在少數(shù)情況下,只能使用同步模式的XMLHttpRequest請(qǐng)求.比如在 window.onunload和window.onbeforeunload 事件處理函數(shù)中。在頁面unload事件處理函數(shù)中使用異步的XMLHttpRequest會(huì)引發(fā)這樣的問題:當(dāng)響應(yīng)返回之后,頁面已經(jīng)不復(fù)存在,所有變量和回調(diào)函數(shù)也已經(jīng)銷毀.結(jié)果只能引起一個(gè)錯(cuò)誤 ,“函數(shù)未定義”。解決辦法是在這里使用同步模式的請(qǐng)求,這樣的話,當(dāng)請(qǐng)求完成之前,頁面不會(huì)被關(guān)閉.
window.onbeforeunload = function () { var oReq = new XMLHttpRequest(); oReq.open("GET", "logout.php?nick=" + escape(myName), false); // 同步請(qǐng)求 oReq.send(null); if (oReq.responseText.trim() !== "已退出"); { // "已退出"是返回的數(shù)據(jù) return "退出失敗,您想手動(dòng)執(zhí)行退出嗎?"; } };
異步請(qǐng)求
使用異步模式的話,當(dāng)數(shù)據(jù)完全請(qǐng)求回來以后,會(huì)執(zhí)行一個(gè)指定的回調(diào)函數(shù), 在執(zhí)行請(qǐng)求的同時(shí),瀏覽器可以正常的執(zhí)行其他事務(wù)的處理。
3.例子: 創(chuàng)建一個(gè)標(biāo)準(zhǔn)的方法來讀取外部文件
在一些需求情況下,必須讀取多個(gè)外部文件. 這是一個(gè)標(biāo)準(zhǔn)的函數(shù). 該函數(shù)使用XMLHttpRequest對(duì)象進(jìn)行異步請(qǐng)求.而且可以為每個(gè)文件讀取完成后指定不同的回調(diào)函數(shù).
function loadFile (sURL, timeout, fCallback /*, 傳入?yún)?shù)1, 傳入?yún)?shù)2, 等 */) { var aPassArgs = Array.prototype.slice.call(arguments, 3), oReq = new XMLHttpRequest(); oReq.ontimeout = function() { console.log("請(qǐng)求超時(shí)."); } oReq.onreadystatechange = function() { if (oReq.readyState === 4) { if (oReq.status === 200) { fCallback.apply(oReq, aPassArgs); } else { console.log("Error", oReq.statusText); } } }; oReq.open("GET", sURL, true); oReq.timeout = timeout; oReq.send(null); }
loadFile函數(shù)的用法:
function showMessage (sMsg) { alert(sMsg + this.responseText); } loadFile("message.txt", 200, showMessage, "New message!\\n");
第1行定義一個(gè)函數(shù),當(dāng)文件讀取完畢后,fCallback函數(shù)會(huì)以第3個(gè)參數(shù)以后的所有參數(shù)為自己的參數(shù)來被調(diào)用.
第3行使用一個(gè)超時(shí)設(shè)置,來避免你的代碼為了等候讀取請(qǐng)求的返回?cái)?shù)據(jù)長(zhǎng)時(shí)間執(zhí)行,通過為XMLHttpRequest對(duì)象的timeout 屬性賦值來指定
第6行為onreadystatechange事件句柄指定了回調(diào)函數(shù),函數(shù)在每次執(zhí)行時(shí),檢查請(qǐng)求是否結(jié)束(請(qǐng)求狀態(tài)為4),如果是的話,判斷請(qǐng)求是否成功(HTTP狀態(tài)嗎是否為200),如果是的話,輸出頁面源碼,如果請(qǐng)求出現(xiàn)了錯(cuò)誤,輸出錯(cuò)誤信息.
第15行指定第三個(gè)參數(shù)為true,表示該請(qǐng)求應(yīng)該以異步模式執(zhí)行.
4.例子: 使用異步請(qǐng)求,不使用閉包.
function switchXHRState() { switch (this.readyState) { case 0: console.log("還沒調(diào)用open()方法."); break; case 1: console.log("還沒調(diào)用send()方法."); break; case 2: console.log("已經(jīng)調(diào)用send()方法,響應(yīng)頭和響應(yīng)狀態(tài)已經(jīng)返回."); break; case 3: console.log("下載中,已經(jīng)得到部分響應(yīng)實(shí)體."); break; case 4: console.log("請(qǐng)求完成!"); this.callback.apply(this, this.arguments); } }; function loadFile (sURL, fCallback /*, 傳入?yún)?shù)1, 傳入?yún)?shù)2, 等 */) { var oReq = new XMLHttpRequest(); oReq.callback = fCallback; oReq.arguments = Array.prototype.slice.call(arguments, 2); oReq.onreadystatechange = switchXHRState; oReq.open("GET", sURL, true); oReq.send(null); }
使用 bind:
function switchXHRState(fCallback, aArguments) { switch (this.readyState) { case 0: console.log("還沒調(diào)用open()方法."); break; case 1: console.log("還沒調(diào)用send()方法."); break; case 2: console.log("已經(jīng)調(diào)用send()方法,響應(yīng)頭和響應(yīng)狀態(tài)已經(jīng)返回."); break; case 3: console.log("下載中,已經(jīng)得到部分響應(yīng)實(shí)體."); break; case 4: console.log("請(qǐng)求完成!"); fCallback.apply(this, aArguments); } }; function loadFile (sURL, fCallback /*, 傳入?yún)?shù)1, 傳入?yún)?shù)2, 等 */) { var oReq = new XMLHttpRequest(); oReq.onreadystatechange = switchXHRState.bind(oReq, fCallback, Array.prototype.slice.call(arguments, 2)); oReq.open("GET", sURL, true); oReq.send(null); }
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
js實(shí)現(xiàn)的簡(jiǎn)單圖片浮動(dòng)效果完整實(shí)例
這篇文章主要介紹了js實(shí)現(xiàn)的簡(jiǎn)單圖片浮動(dòng)效果,以完整實(shí)例形式分析了javascript實(shí)現(xiàn)圖片定時(shí)漂浮移動(dòng)功能的方法,涉及javascript定時(shí)函數(shù)與數(shù)值動(dòng)態(tài)運(yùn)算相關(guān)技巧,需要的朋友可以參考下2016-05-05JavaScript實(shí)現(xiàn)網(wǎng)頁加載進(jìn)度條代碼超簡(jiǎn)單
網(wǎng)頁進(jìn)度條能夠更好的反應(yīng)當(dāng)前網(wǎng)頁的加載進(jìn)度情況,loading進(jìn)度條可用動(dòng)畫的形式從開始0%到100%完成網(wǎng)頁加載這一過程。代碼簡(jiǎn)單易懂,效果非常好,需要的一起學(xué)習(xí)學(xué)習(xí)吧2015-09-09JavaScript中this的用法及this在不同應(yīng)用場(chǎng)景的作用解析
由于其運(yùn)行期綁定的特性,JavaScript 中的 this 含義要豐富得多,它可以是全局對(duì)象、當(dāng)前對(duì)象或者任意對(duì)象,這完全取決于函數(shù)的調(diào)用方式,這篇文章主要給大家介紹了JavaScript中this的用法及this在不同應(yīng)用場(chǎng)景的作用解析,一起看看吧2017-04-04連續(xù)操作HTMLElement對(duì)象圖文解決方法
Object.prototype.***不能用作在HTMLElement對(duì)象上,如本后面的抓圖所示。2008-03-03js實(shí)現(xiàn)方塊上下左右移動(dòng)效果
這篇文章主要為大家詳細(xì)介紹了js實(shí)現(xiàn)方塊上下左右移動(dòng)效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-08-08對(duì)象題目的一個(gè)坑 理解Javascript對(duì)象
這篇文章主要介紹了Javascript對(duì)象,特別為大家分享了對(duì)象題目的一個(gè)坑,提供了解題思路,感興趣的小伙伴們可以參考一下2015-12-12JS奇技之利用scroll來監(jiān)聽resize詳解
這篇文章主要給大家介紹了JS奇技之利用scroll來監(jiān)聽resize的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起看看吧。2017-06-06利用js-cookie實(shí)現(xiàn)前端設(shè)置緩存數(shù)據(jù)定時(shí)失效
這篇文章主要介紹了利用js-cookie實(shí)現(xiàn)前端設(shè)置緩存數(shù)據(jù)定時(shí)失效,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-06-06