2013-04-16 87 views
25

我有一個簡單的ajax調用,正在beforeSend上執行一個函數,並在完成。他們執行得很好,但beforeSend「看似」並沒有執行,直到成功之後。在發送之前有一個「請稍候」通知。如果我在beforeSend中的函數之後休息,那麼它將顯示該通知,然後成功。如果沒有中斷點,那麼它會坐在那裏等待響應,然後等待成功後,我的請稍候通知將出現幾分之一秒。所需的功能是在請求發送後立即顯示通知,以便在等待響應時顯示。jquery ajax beforesend

 $.ajax({ 
      type : 'POST', 
      url : url, 
      async : false, 
      data : postData, 
      beforeSend : function(){ 
       $.blockUI({ 
        fadeIn : 0, 
        fadeOut : 0, 
        showOverlay : false 
       }); 
      }, 
      success : function (returnData) { 
       //stuff 
      }, 
      error : function (xhr, textStatus, errorThrown) { 
       //other stuff 
      }, 
      complete : function(){ 
       $.unblockUI(); 
      } 
     }); 
+1

附註:任何爲什麼'async = false'的原因? – Dom

+0

這是更新頁面上常用的UI。我不希望用戶在執行時使用這些操作。 – user1134179

+2

'beforeSend'與'async:false'結合沒有任何意義。如果你想保持'async:false',你可以在你的'ajax(...)'之前添加'blockUI'調用,因爲代碼將被同步執行。 – Steve

回答

25

你的問題是async:false標誌。除了這是不好的做法(並且在非常有限的情況下確實是唯一有意義的事實)之外,它實際上會隨着代碼其餘部分的執行順序而混亂。這是爲什麼:

看來,在blockUI代碼的某處,他們正在設置一個setTimeout。結果,blockUI代碼等待很短的時間。由於隊列中的下一條指令是ajax()調用,因此blockUI執行被放在後面。而且由於您使用的是async:false,因此必須等到完成ajax調用完成後才能運行。

具體而言,這裏是發生了什麼:

  • 你叫blockUI
  • blockUI有setTimeout和超時完成後(即使超時長度爲0,下一行,ajax()被執行將第一次運行)
  • ajax()調用與async:false,這意味着直到請求成功的返回
  • ajax()返回JS停止一切d JS可以繼續執行
  • blockUI代碼的setTimeout可能已經結束,所以它會是下一步要執行
  • 它看起來像blockUI運行爲success一部分,但在現實中,它剛剛被排隊,因爲超時了

如果你不會使用async:false,執行會去如下:

  • 你叫blockUI
  • blockUI有一個setTimeout並在超時完成後執行(即使超時長度爲0,則下一行ajax()將首先運行)
  • ajax()被調用並向服務器發送請求。
  • 它連接到服務器時,一般JS繼續執行
  • blockUI代碼的setTimeout可能已經結束,所以它會在下除非有更多的JS代碼執行
  • blockUI文本顯示出來
  • 某處,JS執行完成,直到AJAX successcomplete回調執行

這裏有一些的jsfiddle例子來說明這個問題:

Example 1:這是您遇到的情況。在執行ajax調用之後,blockUI文本纔會顯示。

Example 2:這與您的情況完全相同,但撥打ajax之前有alert。由於存在alert,因此blockUI中的超時會將blockUI文本的出現放在alert之後,而不是ajax之後。

Example 3:這是它應該是怎樣不async:false

6

這很可能是因爲async : false。當您的調用是同步的, 您的$.ajax()函數調用開始後,沒有任何反應,直到接收到響應,並儘可能您的代碼放在接下來的事情將是success處理

爲了使它工作,你可以做這樣的事

$.blockUI({ 
     fadeIn : 0, 
     fadeOut : 0, 
     showOverlay : false 
}); 
// and here goes your synchronous ajax call 
$.ajax({ 
      type : 'POST', 
      url : url, 
      async : false, 
      data : postData, 
      success : function (returnData) { 
       //stuff 
      }, 
      error : function (xhr, textStatus, errorThrown) { 
       //other stuff 
      }, 
      complete : function(){ 
       $.unblockUI(); 
      } 
    }); 
+0

我同意你的推理......我想補充一點,在技術上你甚至不需要'complete'回調。您可以在'ajax()'部分之後添加'$ .unblockUI()',因爲它是異步的。 – Steve

+2

我刪除了beforeSend並完成並將.ajax請求之前和之後的邏輯放入,但是功能沒有改變 – user1134179

0
$.blockUI({ 
     fadeIn : 0, 
     fadeOut : 0, 
     showOverlay : false 
}); 
setTimeout(function() { 
    $.ajax({ 
      type : 'POST', 
      url : url, 
      async : false, 
      data : postData, 
      success : function (returnData) { 
       //stuff 
      }, 
      error : function (xhr, textStatus, errorThrown) { 
       //other stuff 
      } 
    }); 
},100); 
$.unblockUI(); 

http://bugs.jquery.com/ticket/7464

0

工作的另一種方法可能是

不完美的
$.orig_ajax = $.ajax; 

$.ajax = function() { 
    var settings = {async: true}; 
    if (2 == arguments.length && 'string' == typeof arguments[0] && 'object' == typeof arguments[1]) 
     settings = arguments[1]; 
    else if (arguments.length && 'object' == typeof arguments[0]) 
     settings = arguments[0]; 

    if (!settings.async && 'function' == typeof settings.beforeSend) { 
     var args = arguments; 

     settings.beforeSend(); 
     var dfd = $.Deferred(); 
     setTimeout(function() { 
      $.orig_ajax.apply($, args).then(dfd.resolve) 
             .fail(dfd.reject); 
     } ,100); 
     return dfd.promise(); 
    } else 
     return $.orig_ajax.apply($, arguments); 
}; 

(因爲不同的超載$就功能延期對象),但可能有所幫助..

相關問題