#javascript #jquery #ajax #jquery-deferred
#javascript #jquery #ajax #jquery-отложенный
Вопрос:
У меня есть функция, которая выглядит примерно так:
function refreshData() {
service.getSettings().done(function (settings) {
// DATA 1
service.getData1(settings).done(function (result) {
// do something local with result
// partial resolve 1
});
// DATA 2
var localData = service.getLocalData();
if (localData.length) {
service.getData2(settings, localData).done(function (result) {
// do something local with result
// partial resolve 2
});
} else {
$('#list').empty();
// or partial resolve 2
}
});
}
Что я хочу сделать, так это создать отложенный объект для этой функции, чтобы я знал, когда обновление данных будет полностью завершено. Я знаю, что мог бы связать их вместе с $.when
, но я хочу, чтобы два вызова AJAX выполнялись независимо, и мне все равно, завершится ли один раньше другого.
Я отметил выше, где я хочу разрешить каждую часть. Я просто не уверен, как это сделать.
Моей конечной целью был бы вызов, подобный этому:
refreshData().done(function() {
// hide loader
});
Ответ №1:
Основные вещи, которые вам нужно сделать, это :
- чтобы вернуть составное обещание, сгенерированное
$.when(partial1, partial2)
- чтобы сгенерировать (и вернуть) это обещание внутри
.then()
, привязанное к вашему внешнемуservice.getSettings()
Вы также можете захотеть сделать сбой наблюдаемых частей, по крайней мере, для отладки.
function refreshData() {
return service.getSettings().then(function (settings) {//note `return` and `.then()`
var partial1, partial2; // declare two promises
// utility function make error observable - avoids repetition below
function handleError(err) {
console.error(err);
});
partial1 = service.getData1(settings).done(function (result) {
//do something local with result
}).fail(handleError);//make failure of partial1 observable
var localData = service.getLocalData();//assume this is synchronous
if (localData.length) {
partial2 = service.getData2(settings, localData).done(function (result) {
//do something local with result
}).fail(handleError);//make failure of partial2 observable
} else {
partial2 = $('#list').empty().promise();//sneaky way to generate a resolved promise
}
return $.when(partial1, partial2);//as we are inside a `.then()`, the promise generated here is effectively returned by refreshData().
});
}
смотрите комментарии в коде
Вызовите следующим образом :
refreshData().done(function() {
// hide loader
}).fail(function(err) {
// indicate failure
});
Комментарии:
1. 1 за использование уже доступных обещаний вместо создания новых отложенных.
Ответ №2:
как насчет чего-то подобного,
function refreshData() {
var def1 = $.Deferred();
var def2 = $.Deferred();
service.getSettings().done(function (settings) {
service.getData1(settings).done(function (result) {
def1.resolve(result);
});
var localData = service.getLocalData();
if (localData.length) {
service.getData2(settings, localData).done(function (result) {
def2.resolve(result);
});
} else {
$('#list').empty();
def2.resolve();
}
});
// return aggregated promise
return $.when(def1, def2);
}
refreshData().done(function(r1, r2) {
// hide loader
});
Примечание: непроверенный
Комментарии:
1. Вам нужны отдельные отсрочки для
def1
иdef2
. Не могу использовать тот же, что у вас здесь. Вероятно, можно было бы также использовать существующие обещания, а не создавать новые.2. @jfriend00 спасибо, приятель, я знал, что найдется решение получше этого, но в то время оно меня не поразило. Roamer-1888 на самом деле элегантен. Отредактировал ans, чтобы указать отдельные отсрочки.