溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

jquery中Ajax的異步和同步

發(fā)布時(shí)間:2020-05-27 13:08:34 來(lái)源:網(wǎng)絡(luò) 閱讀:48289 作者:cnn237111 欄目:web開(kāi)發(fā)

版權(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é)果如下:

jquery中Ajax的異步和同步

這是因?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é)果卻是:

jquery中Ajax的異步和同步

原因很簡(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ì)了。

jquery中Ajax的異步和同步

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è)事件。

向AI問(wèn)一下細(xì)節(jié)

免責(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)容。

AI