2012-03-14 61 views
1
var tds = ["0", "1", "2", "3", "4", "5", "6"]; 

for (var i = 0; i < tds.length; i++) { 

    jQuery("#notification-bar").html('I am doing ' + tds[i]); 

    jQuery.ajax({ 
     url: "/ajax_json_echo/", 
     type: "POST", 
     timeout: 10000, 
     data: tds[i], 
     success: function(response) { 

     }, 
     error: function(x, t, m) { 


     } 
    }); 


} //end for 

jQuery("#notification-bar").html("Done!");​ 

/ajax_json_echo /可能需要10秒鐘甚至更多時間來處理tds。jQuery如何在async爲true時使ajax請求「同步」

通知欄的預期的結果是

我做0

我做1

我做2

...

完成!

實際結果我得到的是:

完成!

我想這是由jQuery的異步變量引起ajax被設置爲true。

如果設置爲false,則瀏覽器將被凍結。當它恢復時,我會得到「完成!」只要。

回答

3

瀏覽器運行JavaScript和不使所有在同一線程上的頁面,所以當JS運行時沒有重繪會發生。這意味着您的整個for循環將完成並且狀態消息將被設置爲「完成!」 之前頁面得到更新。

在async爲true的情況下,所有的Ajax請求都會首先排隊並將消息設置爲「完成!」然後異步處理後的響應。在async設置爲false的情況下,Ajax請求一次只進行一次,直到響應進入時纔會執行。無論哪種方式,瀏覽器都無法顯示「我正在做...」消息。

而不是使用一個循環,你可以從阿賈克斯內觸發每個後續調用完成(或成功)回調:

var tds = ["0", "1", "2", "3", "4", "5", "6"]; 

function doNextAjax(i) { 
    if (i < tds.length) { 
     jQuery("#notification-bar").html('I am doing ' + tds[i]); 

     jQuery.ajax({ 
     url: "/ajax_json_echo/", 
     type: "POST", 
     timeout: 10000, 
     data: tds[i], 
     success: function(response) { 

     }, 
     error: function(x, t, m) {  

     }, 
     complete: function() { 
      doNextAjax(i + 1); 
     } 
     }); 
    } else { 
     jQuery("#notification-bar").html("Done!");​ 
    } 
} 

doNextAjax(0); 

每次doNextAjax()把它叫做更新狀態消息,使一個Ajax請求,並就這樣。當函數退出瀏覽器時,有機會重新渲染並實際顯示該消息。然後,當完成回調被觸發時,它會再次爲下一個項目調用該函數。當沒有物品時,它會設置「完成!」信息。

請注意,使用完整的回調來觸發下一個Ajax調用意味着即使某個特定的請求失敗,它也會繼續運行。如果您想停止出現錯誤,您可以擺脫完整的處理程序並將doNextAjax(i+1)移入成功回調。

+0

謝謝。這就是我要的。 :] – Jesse 2012-03-14 09:01:34

0

通常這就是你使用成功回調參數爲ajax() for - 在AJAX請求完成時運行一個函數。

http://api.jquery.com/jQuery.ajax/

+0

琥珀你好,對不起,你能不能改述你說的話?我不明白... – Jesse 2012-03-14 08:17:06

0

如果你可以使用HTML5元素,使用<progress>元素,這就是爲什麼他的存在。
增加每個ajax請求的成功回調中的進度條值。

var progress = document.getElementById('progress'); 
progress.max = tds.length; 

... 
success: function(){ 
         progress.value++; 
        } 

LIVE DEMO

+0

感謝您的回答。我使用的是jQuery UI,它具有進度條功能。實際上,我把jQuery(「#progress」).progressbar((i /(tds.length - 1))* 100);在成功回調中 – Jesse 2012-03-14 08:14:28

+0

「我在做」的通知對我來說更重要。 – Jesse 2012-03-14 08:16:22

+0

@ user752492。我不明白你面臨的問題是什麼。試着用[小提琴]向我展示(http://jsfiddle.net/) – gdoron 2012-03-14 08:20:13

0

你寫的回覆會發生。更改

jQuery("#notification-bar").html('I am doing ' + tds[i]); 
jQuery("#notification-bar").html("Done!");​ 

jQuery("#notification-bar").append('I am doing ' + tds[i]); 
jQuery("#notification-bar").append("Done!");​ 

,你會看到結果。但是,行爲不是你所期望的。 For循環將一個接一個地激活所有的AJAX調用。如果您只想在最後一次完成時觸發下一個AJAX呼叫,則應使用jQuery Deferred對象來管理此操作。

我已經結束了在這裏的例子http://jsfiddle.net/DXYZw/2/

var tds = ["0", "1", "2", "3", "4", "5", "6"]; 

var sendRequest = function(ary, data) { 
    if (!ary.length) { 
     // no more calls to be made 
     jQuery("#notification-bar").append("Done!"); 
     return; 
    } 
    jQuery("#notification-bar").append('I am doing ' + tds.length); 
    dfAJAX(ary) 
     .done(sendRequest) 
     .fail(function() { 
      alert("error"); 
     }); 
} 

var dfAJAX = function(ary) { 
    var dfd = new jQuery.Deferred(); 

    var dataToSend = ary.pop(); 

    jQuery.ajax({ 
     url: "/ajax_json_echo/", 
     type: "POST", 
     timeout: 10000, 
     data: dataToSend 
    }) 
     .done(function(data) { 
      dfd.resolve(ary, data); 
     }) 
     .fail(function() { 
      dfd.reject(); 
     }) 

    return dfd.promise(); 
} 

sendRequest(tds); 
+0

好的,這是另一種解決方案。很酷的一個。謝謝。我會看看延期對象。 – Jesse 2012-03-15 06:35:54

0

這裏的解決方案,你應該看看jQuery的遞延對象

$.when($.ajax("/page1.php"), $.ajax("/page2.php")).done(function(a1, a2){ 
    /* a1 and a2 are arguments resolved for the 
     page1 and page2 ajax requests, respectively */ 
    var jqXHR = a1[2]; /* arguments are [ "success", statusText, jqXHR ] */ 
    if (/Whip It/.test(jqXHR.responseText)) { 
     alert("First page has 'Whip It' somewhere."); 
    } 
}); 

http://api.jquery.com/jQuery.when/