#javascript #jquery #ajax
#javascript #jquery #ajax
Вопрос:
Я использую jQuery, и у меня есть цикл асинхронных запросов AJAX. Я знаю, что могу дождаться завершения их всех, используя удобный метод ‘$.when.apply(array_of_requests).then()’.
Но у меня также есть другой набор запросов AJAX, которые выполняются только после завершения каждого из первых запросов. Я тоже хочу дождаться их завершения, но я не уверен на 100%, что нашел лучший способ.
Вот упрощенный пример моих запросов:
var intital_data = [1,2,3,4,5,6,7,8,9,10];
var promises = [];
var promises_inner = [];
$.each(intitial_data, function(i, n) {
var ajax_call = $.ajax({url:'http://www.domain.com/etc/' n});
promises.push(ajax_call);
ajax_call.done(function(data) {
var ajax_call_inner = $.ajax({url:'http://www.domain.com/etc/' data.result});
promises_inner.push(ajax_call_inner);
ajax_call_inner.done(function(data) {
// Do something with the content of data here.
});
});
});
Итак, когда каждый из десяти зацикленных AJAX-запросов выполнен, я делаю второй AJAX-запрос на основе результатов первого. Все работает нормально.
Затем у меня есть что-то вроде этого, потому что я хочу дождаться завершения как первых десяти запросов (сохраненных в массиве promises), так и второй партии (сохраненных в promises_inner):
$.when.apply($, promises).then(
function() {
// The ten outer AJAX calls are finished now.
$.when.apply($, promises_inner).then(
function() {
// The inner AJAX calls are finished now.
}
);
}
);
В рамках первой функции $.when.apply().then()’s ‘done’ вторая партия запросов еще не завершена или даже не добавлена в массив promises_inner. Но я обнаружил, что добавление вложенного $.when.apply().then(), похоже, работает — в его функции ‘done’ завершены все запросы.
Но я не уверен, что это лучшее и наиболее надежное решение. Я обеспокоен тем, что это работает только по совпадению — что это вызывает достаточную задержку для завершения вызовов — вместо того, чтобы иметь логический смысл.
Есть ли лучшее, более надежное решение? Спасибо.
Комментарии:
1. Я говорил слишком рано, когда сказал, что это, кажется, работает. Иногда это работает, но в других случаях promises_inner еще не добавил к нему все вложенные AJAX-запросы. Поэтому иногда внутренний $.when происходит до того, как все было возвращено.
Ответ №1:
Взгляните на $.Обратные вызовы в 1.7. Я думаю, вы будете в восторге от гибкости создания собственных «потоков» и возможности их повторного использования, запуска один раз и т.д.
В том, что вы сделали, нет ничего плохого (шаблон apply, возможно, не является первым выбором из большинства, обычно они просто перечисляют их в a $.when(a, b, c ….) — но вам может больше понравиться синтаксис обратных вызовов $.Callbacks.
Комментарии:
1. Спасибо за указатель. Документы $.Callbacks заставляют мой мозг болеть, но я ожидаю, что в конце концов это пройдет! В то же время, считаете ли вы, что мои вложенные $.when … s должны быть надежными?
2. Мы должны делать аналогичные вещи при обработке правил в нашем приложении страхования, потому что задействовано как минимум 10 сервисов. Другая вещь, которую вы можете сделать, которая может быть проще для чтения, — это создать отложенный запрос и разрешить его только после завершения первого запроса when. Используйте это отложенное обещание в качестве . готово для следующего набора обратных вызовов. У Адди Османи есть хорошая статья об обратных вызовах, и, вероятно, скоро появятся новые.
Ответ №2:
Попробуйте это только с одним основным обещанием для полного выполнения (разрешения) за цикл-run (здесь все еще называется inner_promise).
var initial_data = [1,2,3,4,5,6,7,8,9,10];
var promises_inner = [];
initial_data.forEach(function(n) {
// Create promise for the inner call here.
var promise_inner = $.Deferred();
promises_inner.push(promise_inner);
$.ajax({url:'http://www.domain.com/etc/' n}).done(function(data) {
$.ajax({url:'http://www.domain.com/etc/' data.result}).done(function(data) {
// Do something with the content of data here.
promise_inner.resolve();
});
});
});
console.log("promises_inner contains " promises_inner.length " promises") // should contain all the 10 promises
$.when.apply($,promises_inner).done(function() {
// The inner AJAX calls are finished now
})