2011-08-25 56 views
1

我想從多個Ajax請求的返回中獲得總數,現在我使用同步來使它工作,因爲我認爲這將是一個更好的解決方案。從多個Ajax請求中獲取總數

這裏是我的咖啡

get_total = (trend, duration) -> 
    total = 0 
    for keyword in trend.search_terms 
    url = "http://otter.topsy.com/search.json?q=#{keyword}&window=#{duration}" 
    $.ajax 
     url: url 
     async: false 
     success: (data) -> 
     total += data.response.total 
    total 

這很好地編譯成

get_total = function(trend, duration) { 
    var keyword, total, url, _i, _len, _ref; 
    total = 0; 
    _ref = trend.search_terms; 
    for (_i = 0, _len = _ref.length; _i < _len; _i++) { 
     keyword = _ref[_i]; 
     url = "http://otter.topsy.com/search.json?q=" + keyword + "&window=" + duration; 
     $.ajax({ 
     url: url, 
     async: false, 
     success: function(data) { 
      return total += data.response.total; 
     } 
     }); 
    } 
    return total; 
    }; 

有沒有辦法有沒有使用同步JS總的工作。

我一直在試驗$ .when()。then(),但是當請求的大小是動態的時它會引發問題。

回答

4

我不知道CoffeeScript的,所以這裏是一個純粹的jQuery的解決方案:

你不能get_total未做同步調用的值。一旦所有請求都完成,你可以做的就是調用回調函數。

本示例使用jQuery的Deferred objects [docs]的:

function get_total(trend, duration, callback) { 
    var deferreds = [], total = 0; 

    for(var i = 0, l = trend.search_terms.length; i < l; i++) { 
     deferreds.push($.get("http://otter.topsy.com/search.json?q=" + trend.search_terms[i] + "&window=" + duration, function(data) { 
      total += data.response.total; 
     })); 
    } 

    $.when.apply($, deferreds).then(function() { 
     callback(total); 
    }); 
} 

用法:

get_total(trend, 200, function(total) { 
    // now execute the code that needs `total` 
}); 

如果需要get_total返回值,那麼你必須做出同步調用。一般來說,這是一個糟糕的主意,特別是當你提出多個請求時。它會凍結瀏覽器的用戶界面。更好地重構您的代碼以使用回調工作。

更新:我剛剛讀了你的問題的最後一句話。您可以使用.apply()[MDN]將動態數量的參數傳遞給函數。

Update2:當然,如果您對服務有控制權,您應該讓它接受多個關鍵字以避免多個Ajax請求。

+0

如何合計仍然範圍和正確返回。如果你有時間,我希望進入聊天室並與你談談如果你有時間 – austinbv

+0

@austinbv:我創建了一個聊天室:http://chat.stackoverflow.com/rooms/2862/getting-the-total-from -multiple-ajax-requests –

+0

http://chat.stackoverflow.com/rooms/2862/getting-the-total-from-multiple-ajax-requests何時你可以,而ty – austinbv

1

當然,但您需要添加一些狀態跟蹤來確定何時所有ajax請求已返回,然後調用一個函數以傳入生成的總數。如果您切換到異步請求,那麼在發出ajax請求後,會立即返回'total',此時可能只有0個或幾個請求已返回,因此您將得到不正確的總數。

var requestsOutstanding = 0; 
var total = 0; 
for (i = 0; i < _ref.length) { 
    keyword = _ref[i]; 
    url = "..."; 
    requestsOutstanding++; 
    $.ajax({ 
     url: url, 
     async: true, 
     success: function(data) { 
      total += data.response.total; 
      requestsOutstanding--; 
      if (requestsOutstanding == 0) { 
      totalResultIsAvailable(total); // trigger next stage of events here 
      } 
     } 
    }); 
} 
+0

您可能還想添加錯誤處理程序,以防發生任何請求失敗,因此您仍然可以遞減計數器。否則,你永遠不會得到一個總價值,因爲這些請求中的一個(或多個)永遠是「優秀的」。 –

1

我不知道CoffeeScript的,但要做到這一點的JS,你可以使用閉包:

var total_trend = (function() { 
    var total = 0, 
     num_adds = 0; 

    return { 
     add_to_total: function(add) { total += parseInt(add, 10); num_adds += 1; }, 
     get_total: function() { return total; }, 
     get_deferred_total: function(expected, callback) { 
      if(num_adds !== expected) { 
       var _this = this; 
       setTimeout(function(){ return _this.get_deferred_total(expected, callback); }, 100); 
      } else { 
       callback(total); 
      } 
     } 
    }; 
})(); 

將此定義爲你的回調可以訪問的變量,然後在Ajax回調做:

total_trend.add_to_total(data.response.total); 

,當你想要的總:

total_trend.get_total(); 

,如果你想總直至add_to_total推遲已經有一定數量的呼叫:

var expected_num_calls = 5; 
total_trend.get_deferred_total(expected_num_calls, function(total) { alert(total); }) 

在上面的情況下,當add_to_total被調用5次時,回調函數將被調用。


編輯:正如費利克斯所指出的,原始版本不支持等到ajax調用完成。代碼已更新,以支持推遲總數。這應該起作用,但Felix的答案在這一點上可能會更清晰一些。

+0

但你怎麼知道所有的Ajax調用已完成? –

+0

好點...你可以在total_trend var中保存添加的數量我想,但邏輯會變得有點混亂。 –