2013-04-05 248 views
6

我想寫一個函數執行一打異步ajax請求,等待所有的完成,然後返回聚合信息。像:等待異步ajax請求完成

function countHealthy(urls) { 
    var healthy = 0; 
    for (var i = 0; i < urls.length; ++i) { 
    $.ajax({url: urls[i], async: true, id: i}) 
    .done(function (data) { ++healthy; }); 
    } 
    // Wait for all ajax to finish. 
    return healthy; 
} 

PS:++健康線程是否安全?

回答

6

Javascript沒有線程,所以線程安全不是問題。你的return語句是問題,它需要在回調中完成ajax調用的執行。由於ajax是異步發生的,因此您的代碼所在的位置會在所有請求返回之前觸發return語句。

你可能想看看query deferreds,這似乎是出於這種類型的事情。直接從那個鏈接

function doAjax() { 
    return $.get('foo.htm'); 
} 

function doMoreAjax() { 
    return $.get('bar.htm'); 
} 

$.when(doAjax(), doMoreAjax()) 
    .done(function() { 
    console.log('I fire once BOTH ajax requests have completed!'); 
    }) 
    .fail(function() { 
    console.log('I fire if one or more requests failed.'); 
    }); 

隨着一些小的重構,你可以在大約2分鐘內實現這一點。

或者,如果您控制服務器,則可以創建一個服務器端點,在一個請求中執行所有檢查。

1

你可以這樣做:

var urls= ['url1', 'url2', 'url3', 'url4']; 
function doTheUrl() { 
    if (urls.length === 0) { 
     alert('All urls are done now.'); 
     return; 
    } 

    var url = urls.pop(); 
    $.ajax({ 
     url: "/DoTheJob", 
     complete: function() { 
      doTheUrl(); 
     } 
    }); 
}; 
+0

其實我不認爲這會工作。在函數結尾處有一個隱式的'return'。所以當$ .ajax調用被放在堆棧上時,所有事情都會繼續前進,並且函數將退出。我現在會倒下。 – the0ther 2015-03-16 16:19:34

0

也許你可以試試這個。我只是運行一個空的while循環,以便返回語句在所有ajax調用返回之前不會被打中。

function countHealthy(urls) { 
    var healthy = 0; 
    var urlCount = urls.length; 
    var numberOfAjaxCallsReturned = 0; 
    for (var i = 0; i < urls.length; ++i) { 
    $.ajax({url: urls[i], async: true, id: i}) 
     .done(function (data) { 
       ++healthy; 
       numberOfAjaxCallsReturned++; 
     }); 
    } 
    while(numberOfAjaxCallsReturned!=urlCount) 
    { 
    } 
    return healthy; 
} 
+1

這個表現很糟糕,在我看來沒有用。 – 2015-02-25 13:47:51

0

如果您有一個複雜的頁面,您只需要跟蹤並等待異步調用返回。這是因爲其他非十字形的呼叫可能正在運行。

這就是說,簡單的網頁,你可以檢查,並等待沒有電話。這個jQuery腳本會檢查每個季度,看看每個季度是否有當前的異步請求。一旦沒有,你會繼續。

var WaitForAjax = function() 
    { 
     if (jQuery.active == 0){ 
     } 
     else 
     { 
      setTimeout(WaitForAjax, 250); 
     } 
    } 

    function RunIt() 
    { 
     //IssueAjaxCalls would be where you make all your Ajax calls. 
     IssueAjaxCalls(); 

     WaitForAjax(); 

     //The KeepGoing function won't get called until there are no more Ajax calls pending. 
     KeepGoing(); 
    } 
0

首先,你正在每個for循環上做一個ajax請求,這似乎有點浪費你的服務器資源。 如果這個函數會被調用很多,那麼我建議你重構你的代碼 以減少查詢的次數。

不管怎麼說,這裏的如何我會做到這一點

function countHealthy(urls) { 

    var healthy = 0; 
    var reqs = []; 

    for (var i = 0; i < urls.length; ++i) { 
     reqs.push(
      $.ajax({ 
       url: urls[i], 
       id: i 
      }) 
     ); 
    } 
} 


$.when.apply($, reqs).then(function() { 
    // On success 
    ++healthy; 
}).fail(function() { 
    // When failed 
}).always(function() { 
    // this will be run no matter the outcome 
}); 

還沒有嘗試一下的機會,所以我不知道如果我犯了一個語法錯誤等 更改你的一段代碼:

刪除async = true,如果你之前在你的代碼的某個地方將其設置爲false,則忽略此項。

你可以得到如何「when.apply」作品的想法, source