Пользовательские отложенные функции jquery
У меня есть три функции, которые я пытаюсь запустить, первые две делают некоторые асинхронные вещи, которым нужны данные для третьего пользователя. Я хочу, чтобы третья функция срабатывала только при выполнении 1 и 2. это общая структура, но конечная функция срабатывает до окончания 1 и 2.
function run() {
var data1 = {};
var data2 = {};
$.when(first(), second()).done(constructData());
function first() {
var d = new $.Deferred();
//do a bunch of stuff async
data1 = {};
d.resolve();
}
function second() {
var d = new $.Deferred();
//do a bunch of stuff async
data2 = {};
d.resolve();
}
function constructData() {
//do stuff with data1 and data2
}
}
Ответ заключался в немедленном вызове данных конструкции
$.when(first(), second()).done(constructData);
Ответы
Ответ 1
Вы должны вернуть объект обещания. У вас также есть ошибка в этой строке:
$.when(first(), second()).done(constructData());
он должен быть
$.when(first(), second()).done(constructData); // don't call constructData immediately
Итак, все вместе это может быть:
function run() {
var data1 = {};
var data2 = {};
$.when(first(), second()).done(constructData);
function first() {
return $.Deferred(function() { // <-- see returning Deferred object
var self = this;
setTimeout(function() { // <-- example of some async operation
data1 = {func: 'first', data: true};
self.resolve(); // <-- call resolve method once async is done
}, 2000);
});
}
function second() {
return $.Deferred(function() {
var self = this;
setTimeout(function() {
data2 = {func: 'second', data: true};
self.resolve();
}, 3000);
});
}
function constructData() {
//do stuff with data1 and data2
console.log(data1, data2);
}
}
http://jsfiddle.net/FwXZC/
Ответ 2
Я думаю, что вы должны first()
и second()
вернуть обещание: return d.promise();
. Из docs:
Если один аргумент передается в jQuery.when и он не является Отсроченным или обещанием, он будет рассматриваться как разрешенный Deferred, и любые прикрепленные файлы doneCallbacks будут выполнены немедленно.
Я подозреваю, что это может быть причиной того, что вызов when
вызывает constructData
слишком рано.
Трудно сказать из вашего кода, но убедитесь, что вы вызываете d.resolve()
после завершения асинхронных операций.
Вы можете обнаружить, что более естественным подходом к явным установкам data1
и data2
является вместо этого использование данных, которые предоставляются при вызове resolve
. Это означало бы, что ваш вызов when
будет выглядеть примерно так:
$.when(first(), second()).done(function(result1, result2) {
data1 = result1[0];
data2 = result2[0];
constructData();
});
Обратите внимание, что точный формат результатов, предоставляемых методу done
, зависит от характера отложенных объектов. Если promises возвращаются из вызова $.ajax
, результаты должны иметь вид [data, statusText, jqXhrObject]
.