jquery中Ajax的非同步和同步

來源:互聯網
上載者:User

jquery中預設的ajax調用方法是非同步,因此稍不注意就會出錯。比如有一個例子,要求通過ajax檢查一個數是奇數還是偶數。某人不加思索的寫出如下的代碼:

 
  1. $(function () {  
  2.     $("#btntest").click( function(){  
  3.         var s=checkodd(5);  
  4.         alert(s);  
  5.     });  
  6. });  
  7.  
  8. function checkodd(i) {  
  9.     var options = {  
  10.         type: 'POST',  
  11.         url: "test.ashx",  
  12.         data: { "i": i },  
  13.         success: function (result) {  
  14.             if (result.code > 0) {  
  15.                 return "odd";  
  16.             }  
  17.             else {  
  18.                 return "even";  
  19.             }  
  20.         },  
  21.         dataType: "json",  
  22.         error: function (result) {  
  23.             alert("error");  
  24.         }  
  25.     };  
  26.     $.ajax(options);   
  27. }   

其中test.ashx會在接到請求後,如果傳入的i是奇數則返回json格式的資料{"code":"1"},如果是偶數,則返回{"code":"-1"}。

寫下這樣的代碼後,運行後得到的結果如下:

650) this.width=650;" style="border-bottom: 0px; border-left: 0px; border-top: 0px; border-right: 0px" title="clipboard" border="0" alt="clipboard" height="184" src="http://www.bkjia.com/uploads/allimg/131228/1235205Q6-0.png" />

這是因為success方法裡面的return,僅僅是對success方法的傳回值,而不是checkodd的傳回值,這樣的傳回值是無法直接由checkodd方法做得到的。

因此,某人修改代碼如下:

 

 
  1. function checkodd(i) {  
  2.     var returnvalue;  
  3.     var options = {  
  4.         type: 'POST',  
  5.         url: "test.ashx",  
  6.         data: { "i": i },  
  7.         success: function (result) {  
  8.             if (result.code > 0) {  
  9.                 returnvalue = "odd";  
  10.             }  
  11.             else {  
  12.                 returnvalue = "even";  
  13.             }  
  14.         },  
  15.         dataType: "json",  
  16.         error: function (result) {  
  17.             alert("error");  
  18.         }  
  19.     };  
  20.     $.ajax(options);   
  21.     return returnvalue;  

 

通過一個中間變數returnvalue來擷取傳回值。看上去還不錯。但是運行後得到的結果卻是:

650) this.width=650;" style="border-bottom: 0px; border-left: 0px; border-top: 0px; border-right: 0px" title="clipboard[1]" border="0" alt="clipboard[1]" height="184" src="http://www.bkjia.com/uploads/allimg/131228/123520B09-1.png" />

原因很簡單,忽略了ajax預設情況下是非同步執行的,也就是說,在ajax方法沒有運行完,即success方法都沒運行完成之前,已經將returnvalue的值返回出去了,那當然就得到undefined的值。

jquery的ajax提供了async參數,通過設定該參數的值為false,可以避免非同步執行。因此,某人再次修改代碼:

 

 
  1. function checkodd(i) {  
  2.     var returnvalue;  
  3.     var options = {  
  4.         type: 'POST',  
  5.         url: "test.ashx",  
  6.         data: { "i": i },  
  7.         async:false,  
  8.         success: function (result) {  
  9.             if (result.code > 0) {  
  10.                 returnvalue = "odd";  
  11.             }  
  12.             else {  
  13.                 returnvalue = "even";  
  14.             }  
  15.         },  
  16.         dataType: "json",  
  17.         error: function (result) {  
  18.             alert("error");  
  19.         }  
  20.     };  
  21.     $.ajax(options);   
  22.     return returnvalue;  

 

這次終於對了。

650) this.width=650;" style="border-bottom: 0px; border-left: 0px; border-top: 0px; border-right: 0px" title="clipboard[2]" border="0" alt="clipboard[2]" height="186" src="http://www.bkjia.com/uploads/allimg/131228/123520HA-2.png" />

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比較費勁,可以看下面的代碼。

 

 
  1. function useXMLHttpRequest() {  
  2.     var xmlhttp = new XMLHttpRequest();  
  3.     xmlhttp.open("POST", "test.ashx", false);  
  4.     xmlhttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8");  
  5.     xmlhttp.onreadystatechange = function () {  
  6.         if (xmlhttp.readyState == 4) {  
  7.             //alert(xmlhttp.responseText);  
  8.             if (xmlhttp.responseText.code > 0) {  
  9.                 alert("odd");  
  10.             }  
  11.             else {  
  12.                 alert("even");  
  13.             }  
  14.         }  
  15.     };  
  16.     xmlhttp.send("i=5");  
  17.     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處理這個事件。

本文出自 “一隻部落格” 部落格,請務必保留此出處http://cnn237111.blog.51cto.com/2359144/1038080

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.