版權聲明: 本文由 一隻博客 發表於 bloghome博客javascript
jquery中默認的ajax調用方法是異步的,所以稍不注意就會出錯。好比有一個例子,要求經過ajax檢查一個數是奇數仍是偶數。某人不加思索的寫出以下的代碼:jquery
$(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"}。ajax
寫下這樣的代碼後,運行後獲得的結果以下:json
這是由於success方法裏面的return,僅僅是對success方法的返回值,而不是checkodd的返回值,這樣的返回值是沒法直接由checkodd方法作獲得的。瀏覽器
所以,某人修改代碼以下:app
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的值。async
jquery的ajax提供了async參數,經過設置該參數的值爲false,能夠避免異步執行。所以,某人再次修改代碼:ide
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處理這個事件。