您好,登錄后才能下訂單哦!
版權(quán)聲明: 本文由 一只博客 發(fā)表于?bloghome博客
文章鏈接:?https://www.bloghome.com.cn/user/cnn237111
jquery中默認(rèn)的ajax調(diào)用方法是異步的,因此稍不注意就會(huì)出錯(cuò)。比如有一個(gè)例子,要求通過(guò)ajax檢查一個(gè)數(shù)是奇數(shù)還是偶數(shù)。某人不加思索的寫(xiě)出如下的代碼:
$(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會(huì)在接到請(qǐng)求后,如果傳入的i是奇數(shù)則返回json格式的數(shù)據(jù){"code":"1"},如果是偶數(shù),則返回{"code":"-1"}。
寫(xiě)下這樣的代碼后,運(yùn)行后得到的結(jié)果如下:
這是因?yàn)閟uccess方法里面的return,僅僅是對(duì)success方法的返回值,而不是checkodd的返回值,這樣的返回值是無(wú)法直接由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;?? }
?
通過(guò)一個(gè)中間變量returnvalue來(lái)獲取返回值??瓷先ミ€不錯(cuò)。但是運(yùn)行后得到的結(jié)果卻是:
原因很簡(jiǎn)單,忽略了ajax默認(rèn)情況下是異步執(zhí)行的,也就是說(shuō),在ajax方法沒(méi)有運(yùn)行完,即success方法都沒(méi)運(yùn)行完成之前,已經(jīng)將returnvalue的值返回出去了,那當(dāng)然就得到undefined的值。
jquery的ajax提供了async參數(shù),通過(guò)設(shè)置該參數(shù)的值為false,可以避免異步執(zhí)行。因此,某人再次修改代碼:
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;?? }
?
這次終于對(duì)了。
async:false這樣設(shè)置,使得ajax必須執(zhí)行完成后,才可執(zhí)行下面的代碼,因此在適當(dāng)?shù)那闆r下,要修改ajax的參數(shù)來(lái)保證同步運(yùn)行。
事實(shí)上,jquery的ajax本質(zhì)上調(diào)用了XMLHttpRequest對(duì)象。XMLHttpRequest是一個(gè)API,各個(gè)瀏覽器對(duì)它都有各自的實(shí)現(xiàn)。比如老版本的IE用的是ActiveX, Firefox使用XMLHttpRequest對(duì)象。這個(gè)API主要實(shí)現(xiàn)javascript進(jìn)行HTTP(S)通信。詳細(xì)的說(shuō)明可以參與維基百科http://en.wikipedia.org/wiki/XMLHttpRequest。
直接使用該API實(shí)現(xiàn)ajax比較費(fèi)勁,可以看下面的代碼。
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");?? }
?
上面的代碼實(shí)現(xiàn)了前面jquery的ajax的功能,編寫(xiě)起來(lái)比較麻煩,要設(shè)置一些參數(shù)等等,其中xmlhttp.open("POST", "test.ashx", false);中,最后的參數(shù)false或者true是控制ajax為同步還是異步,和前面的jquery的ajax例子中的一個(gè)意思。所以jquery對(duì)該API做了包裝,使得用jquery操作ajax更方便。
有一點(diǎn)要注意,Javascript自身是單線程運(yùn)行的,所有的主流瀏覽器只提供一個(gè)線程執(zhí)行Javascript。因此Javascript不能開(kāi)啟額外的線程(除非使用Web Workers,目前最新的瀏覽器 Safari, Chrome, Opera and Mozilla Firefox支持Web Workers,IE10也會(huì)支持)。Javascript中的事件都是線性執(zhí)行的,通過(guò)一個(gè)任務(wù)隊(duì)列,可以近似的看做先進(jìn)先出的模式處理事件的,因此所有的Javascript異步實(shí)現(xiàn)都是假象,通過(guò)計(jì)時(shí)器實(shí)現(xiàn)的。
Javascript自身單線程運(yùn)行,不代表ajax是單線程運(yùn)行,因?yàn)閍jax是通過(guò)XMLHttpRequest這個(gè)API實(shí)現(xiàn)的,因此是瀏覽器提供額外的線程去處理http request。一旦請(qǐng)求處理完畢,它會(huì)觸發(fā)一個(gè)事件,把這個(gè)事件加入到j(luò)avascript任務(wù)隊(duì)列中,直到j(luò)avascript處理這個(gè)事件。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。