Я пытаюсь получить общую сумму от возврата нескольких запросов 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 (), но он вызывает проблемы, когда размер запросов является динамическим.
3 ответа
Я не знаю CoffeeScript, поэтому вот чистое решение jQuery:
Вы не можете вернуть значение из get_total
без синхронных вызовов. Что вы можете сделать, так это вызвать обратный вызов после завершения всех запросов.
В этом примере используются объекты Deferred
[docs] < / sup> :
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] .
Обновление2: Конечно, если вы контролируете службу, вы должны заставить ее принимать несколько ключевых слов, чтобы избежать множественных запросов Ajax.
Конечно, но вам нужно добавить отслеживание состояния, чтобы выяснить, когда все запросы ajax вернулись, а затем вызвать функцию для передачи сгенерированного итога. Если вы переключитесь на асинхронные запросы, то «total» будет возвращено сразу после того, как будут запущены запросы ajax, и к этому времени, возможно, будет возвращено только 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
}
}
});
}
Я не знаю 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. Код был обновлен, чтобы поддерживать отсрочку итоговой суммы. Это должно сработать, но ответ Феликса, вероятно, на данный момент немного чище.
Похожие вопросы
Новые вопросы
jquery
jQuery - это библиотека JavaScript, рассмотрите возможность добавления тега JavaScript. jQuery - это популярная кросс-браузерная библиотека JavaScript, которая облегчает прохождение Document Object Model (DOM), обработку событий, анимацию и взаимодействие AJAX, сводя к минимуму расхождения между браузерами. Вопрос с тегом jQuery должен быть связан с jQuery, поэтому jQuery должен использоваться в рассматриваемом коде, и в вопросе должны быть как минимум элементы, связанные с использованием jQuery.