版權聲明: 本文由 一只博客 發表于?bloghome博客
文章鏈接:?https://www.bloghome.com.cn/user/cnn237111
jquery中默認的ajax調用方法是異步的,因此稍不注意就會出錯。比如有一個例子,要求通過ajax檢查一個數是奇數還是偶數。某人不加思索的寫出如下的代碼:
$(function?()?{?? ????$("#btntest").click(?function(){?? ????????var?s=checkodd(5);?? ????????alert(s);?? ????});?? });?? ? function?checkodd(i)?{?? ????var?options?=?{?? ????????type:?'POST',?? ????????url:?"test.ashx",?? ????????data:?{?"i":?i?},?? ????????success:?function?(result)?{?? ????????????if?(result.code?>?0)?{?? ????????????????return?"odd";?? ????????????}?? ????????????else?{?? ????????????????return?"even";?? ????????????}?? ????????},?? ????????dataType:?"json",?? ????????error:?function?(result)?{?? ????????????alert("error");?? ????????}?? ????};?? ????$.ajax(options);??? }
其中test.ashx會在接到請求后,如果傳入的i是奇數則返回json格式的數據{"code":"1"},如果是偶數,則返回{"code":"-1"}。
寫下這樣的代碼后,運行后得到的結果如下:
這是因為success方法里面的return,僅僅是對success方法的返回值,而不是checkodd的返回值,這樣的返回值是無法直接由checkodd方法做得到的。
因此,某人修改代碼如下:
function?checkodd(i)?{?? ????var?returnvalue;?? ????var?options?=?{?? ????????type:?'POST',?? ????????url:?"test.ashx",?? ????????data:?{?"i":?i?},?? ????????success:?function?(result)?{?? ????????????if?(result.code?>?0)?{?? ????????????????returnvalue?=?"odd";?? ????????????}?? ????????????else?{?? ????????????????returnvalue?=?"even";?? ????????????}?? ????????},?? ????????dataType:?"json",?? ????????error:?function?(result)?{?? ????????????alert("error");?? ????????}?? ????};?? ????$.ajax(options);??? ????return?returnvalue;?? }
?
通過一個中間變量returnvalue來獲取返回值??瓷先ミ€不錯。但是運行后得到的結果卻是:
原因很簡單,忽略了ajax默認情況下是異步執行的,也就是說,在ajax方法沒有運行完,即success方法都沒運行完成之前,已經將returnvalue的值返回出去了,那當然就得到undefined的值。
jquery的ajax提供了async參數,通過設置該參數的值為false,可以避免異步執行。因此,某人再次修改代碼:
function?checkodd(i)?{?? ????var?returnvalue;?? ????var?options?=?{?? ????????type:?'POST',?? ????????url:?"test.ashx",?? ????????data:?{?"i":?i?},?? ????????async:false,?? ????????success:?function?(result)?{?? ????????????if?(result.code?>?0)?{?? ????????????????returnvalue?=?"odd";?? ????????????}?? ????????????else?{?? ????????????????returnvalue?=?"even";?? ????????????}?? ????????},?? ????????dataType:?"json",?? ????????error:?function?(result)?{?? ????????????alert("error");?? ????????}?? ????};?? ????$.ajax(options);??? ????return?returnvalue;?? }
?
這次終于對了。
async:false這樣設置,使得ajax必須執行完成后,才可執行下面的代碼,因此在適當的情況下,要修改ajax的參數來保證同步運行。
事實上,jquery的ajax本質上調用了XMLHttpRequest對象。XMLHttpRequest是一個API,各個瀏覽器對它都有各自的實現。比如老版本的IE用的是ActiveX, Firefox使用XMLHttpRequest對象。這個API主要實現javascript進行HTTP(S)通信。詳細的說明可以參與維基百科http://en.wikipedia.org/wiki/XMLHttpRequest。
直接使用該API實現ajax比較費勁,可以看下面的代碼。
function?useXMLHttpRequest()?{?? ????var?xmlhttp?=?new?XMLHttpRequest();?? ????xmlhttp.open("POST",?"test.ashx",?false);?? ????xmlhttp.setRequestHeader("Content-Type",?"application/x-www-form-urlencoded;charset=UTF-8");?? ????xmlhttp.onreadystatechange?=?function?()?{?? ????????if?(xmlhttp.readyState?==?4)?{?? ????????????//alert(xmlhttp.responseText);?? ????????????if?(xmlhttp.responseText.code?>?0)?{?? ????????????????alert("odd");?? ????????????}?? ????????????else?{?? ????????????????alert("even");?? ????????????}?? ????????}?? ????};?? ????xmlhttp.send("i=5");?? ????alert("finished");?? }
?
上面的代碼實現了前面jquery的ajax的功能,編寫起來比較麻煩,要設置一些參數等等,其中xmlhttp.open("POST", "test.ashx", false);中,最后的參數false或者true是控制ajax為同步還是異步,和前面的jquery的ajax例子中的一個意思。所以jquery對該API做了包裝,使得用jquery操作ajax更方便。
有一點要注意,Javascript自身是單線程運行的,所有的主流瀏覽器只提供一個線程執行Javascript。因此Javascript不能開啟額外的線程(除非使用Web Workers,目前最新的瀏覽器 Safari, Chrome, Opera and Mozilla Firefox支持Web Workers,IE10也會支持)。Javascript中的事件都是線性執行的,通過一個任務隊列,可以近似的看做先進先出的模式處理事件的,因此所有的Javascript異步實現都是假象,通過計時器實現的。
Javascript自身單線程運行,不代表ajax是單線程運行,因為ajax是通過XMLHttpRequest這個API實現的,因此是瀏覽器提供額外的線程去處理http request。一旦請求處理完畢,它會觸發一個事件,把這個事件加入到javascript任務隊列中,直到javascript處理這個事件。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。