我想从多个ajax请求的返回中得到一个总数,我现在使用sync来使其工作,因为我认为这将是一个更好的解决方案。
这是我的咖啡
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()但是当请求的大小是动态的时候会导致问题。
答案 0 :(得分: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
来返回值,则必须进行同步调用。一般来说,这是一个坏主意,尤其是在您提出多个请求时。它将冻结浏览器的UI。最好重构代码以使用回调。
更新:我刚看完你问题的最后一句话。您可以使用.apply()
[MDN]将动态数量的参数传递给函数。
Update2:当然,如果您可以控制该服务,则应该接受多个关键字以避免多个Ajax请求。
答案 1 :(得分: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
}
}
});
}
答案 2 :(得分: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次时,将调用回调函数。