jQuery . при устранении неполадок с переменным числом аргументов
У меня проблема с использованием jQuery.when() для ожидания завершения нескольких ajax-запросов перед вызовом другой функции.
Каждый запрос ajax будет получать данные JSON и выглядеть примерно так:
function loadData(arg){
var ajaxCall = $.ajax(
URL // depends on arg
)
.error( .... );
return ajaxCall;
}
Когда запрос вызывается, возвращаемое значение (ajaxCall) добавляется в список с именем ajaxRequests.
ajaxRequests = [];
ajaxREquests.push(loadData(arg))
Когда все запросы сделаны, я пытаюсь передать ajaxRequests в $.when, чтобы дождаться завершения всех запросов.
var defer = $.when.apply($, ajaxRequests);
defer.done(function(args){
for (var i=0; i<args.length; i++){
inst.loadData($.parseJSON(args[i].responseText));
}
inst.draw();
});
inst - это объект, который загружает и рисует графики на основе данных JSON.
Проблема в том, что он, похоже, фактически не ожидает завершения запросов - args [i] является объектом, но responseText не определен при выполнении кода. Если я сохраню args [i] и получу к нему доступ позже из консоли, это сработает.
Я подозреваю, что проблема связана с использованием.when с произвольным числом аргументов, поскольку все примеры, которые я видел в Интернете, дают ему заранее определенный список аргументов.
Я не уверен, что использование apply было правильной идеей или нет, но в любом случае это не работает должным образом и ведет себя хаотично (зависит от браузера).
Любая помощь будет принята с благодарностью.
Пожалуйста, дайте мне знать, если требуется дополнительная информация.
Я использую jQuery 1.5
4 ответа
Хотя Алекс действительно обеспечил решение своей проблемы, мне было немного трудно следовать ей. У меня была проблема, похожая на его, которую я решил, и я хотел поделиться своим решением для всех, кому нужно обрабатывать переменное число запросов AJAX.
// Array of requests
var requests = Array();
requests.push($.get('responsePage.php?data=foo'));
requests.push($.get('responsePage.php?data=bar'));
var defer = $.when.apply($, requests);
defer.done(function(){
// This is executed only after every ajax request has been completed
$.each(arguments, function(index, responseData){
// "responseData" will contain an array of response information for each specific request
});
});
В дополнение к ответу Энди Кормана (я все еще не могу ответить на сообщение, я думаю...), если у вас есть только один запрос, информация об ответе будет передана непосредственно в defer.done - функцию в качестве аргумента; Таким образом, вы должны предоставить if для этого случая:
// Array of requests
var requests = Array();
requests.push($.get('responsePage.php?data=foo'));
var defer = $.when.apply($, requests);
defer.done(function(){
// This is executed only after every ajax request has been completed
if (requests.length == 1)
// "arguments" will be the array of response information for the request
else
$.each(arguments, function(index, responseData){
// "responseData" will contain an array of response information for each specific request
});
});
Я думаю, что я решил это сейчас - проблема была в обработке возвращенных аргументов..done получал только три аргумента - текст ответа, статус и объект jqXHR. Я ожидал, что он получит объект jqXHR, полученный в результате каждого запроса.
Я решил это, переместив код обратного вызова для каждого запроса в отдельную функцию (то есть вызов ajax в loadData теперь определяет функцию обратного вызова, которая выполняет вызов '.loadData(...)'), и единственное, что делается вызовом.done является inst.draw(). Кажется, это работает нормально: каждый отдельный обратный вызов выполняется перед.done().
Я не уверен, что это именно так, как это должно работать, но похоже, что делает работу.
Попробуйте ajaxStart и ajaxStop, у которых есть слушатели для открытых запросов ajax.
http://api.jquery.com/ajaxStart/ http://api.jquery.com/ajaxStop/