#ajax #jquery #synchronization
#ajax #jquery #синхронизация
Вопрос:
У меня следующая ситуация: мне нужно выполнять синхронизированные Ajax-запросы в цикле и отображать возвращенный результат после каждой итерации в div-элементе (добавляемом сверху с предыдущими результатами внизу). Время отклика каждого запроса может отличаться, но порядок, в котором они должны отображаться, должен быть таким же, как и выданный. Вот пример с 3 запросами. Допустим, для запроса «A» требуется 3 секунды, «B» — 1 секунда, а «C» — 5 секунд. Порядок, в котором я хочу отобразить результат, — A, B, C по мере выдачи запросов, но код, который я использую, показывает результаты в B, A, C.
Вот код (запрос jQuery Ajax):
$(document).ready(function(){
var json = document.getElementById("hCategories").value;
var categories = eval( '(' json ')' );
for(curCat in categories) {
curCatKey = categories[curCat]['grKey'];
$.ajax({
type: "POST",
url: "get_results.php",
data: "category=" escape(curCatKey)
"amp;search=" escape($("#hQuery").val()),
timeout: 8000,
async: false,
success: function(data) {
$("#content").append(data);
}
});
});
Я думал, что это будет работать с «async:false», но затем он ожидает завершения каждого вызова Ajax и представляет результаты после цикла. Я надеюсь, что некоторые из вас могут указать на некоторые другие решения, я в значительной степени застрял.
Заранее спасибо, приветствую Криса
РЕДАКТИРОВАТЬ: Спасибо за все возможные решения, я попробую их сейчас одно за другим и вернусь с тем, которое соответствует моей проблеме.
Комментарии:
1. Разве вы не можете использовать обратные вызовы или сортировать их впоследствии по идентификатору? AJAX — это, конечно, асинхронный JavaScript и XML.
2. Вы собираетесь заморозить пользовательский интерфейс на 8 секунд в ожидании результатов? Вы не можете быть серьезны.
Ответ №1:
У меня есть два предложения по решению этой проблемы:
Заполнение сгенерированных divs
Вы могли бы генерировать divs с идентификаторами в цикле и заполнять их по завершении запроса:
$(document).ready(function() {
var json = document.getElementById("hCategories").value;
var categories = eval('(' json ')');
for (curCat in categories) {
(function(curCat) {
var curCatKey = categories[curCat]['grKey'];
$('#content').append('<div id="category-"' escape(curCat) '/>');
$.ajax({
type: "POST",
url: "get_results.php",
data: "category=" escape(curCatKey) "amp;search=" escape($("#hQuery").val()),
success: function(data) {
$("#category-" escape(curCat)).html(data);
}
});
})(curCat);
}
});
Или используйте отложенный
Вы можете сохранить объекты jqXHR в массиве и использовать отложенный вызов для успешного выполнения функций по порядку, когда все вызовы завершатся.
$(document).ready(function() {
var json = document.getElementById("hCategories").value;
var categories = eval('(' json ')');
var requests;
for (curCat in categories) {
var curCatKey = categories[curCat]['grKey'];
requests.push($.ajax({
type: "POST",
url: "get_results.php",
data: "category=" escape(curCatKey) "amp;search=" escape($("#hQuery").val())
}));
}
$.when.apply(requests).done(function() {
for (i in requests) {
requests[i].success(function(data) {
$("#content").append(data);
});
}
});
});
Преимущество первого метода в том, что он непрерывно заполняет контейнеры. Я не тестировал ни одну из этих функций, но логика должна работать так, как я ее описал.
Ответ №2:
Это сделало бы свое дело
var results = [];
var idx = 0;
for(curCat in categories) {
curCatKey = categories[curCat]['grKey'];
(function( i ) {
$.ajax({
type: "POST",
url: "get_results.php",
data: "category=" escape(curCatKey)
"amp;search=" escape($("#hQuery").val()),
timeout: 8000,
async: false,
success: function(data) {
results[i] = data;
if (i == idx - 1) { // last one
for (var j=0; j < results.length; j ) {
$("#content").append(results[j]);
}
}
}
});
})(idx );
Ответ №3:
Я думаю, что что-то вроде этого — это то, что вы ищете. Возможно, потребуется некоторая настройка, я немного устал от Deferred. Однако почитайте об этом, очень мощный
deferred = $.Deferred()
for(curCat in categories) {
deferred.pipe(
function(resp){
postData = {} // set up your data...
return $.post("get_results.php", {data: postData, timeout: 8000})
.done(function(content){ $("#content").append(content) })
})
)
}
// Trigger the whole chain of requests
deferred.resolve()