Как связать последовательность отложенных функций в jQuery 1.8.x?
Учитывая эти функции:
function func1() {
var dfd = $.Deferred();
setTimeout(function() {
dfd.resolve('Password');
}, 1000);
return dfd.promise();
}
function func2(message) {
var dfd = $.Deferred();
setTimeout(function() {
if (message == 'Password') {
dfd.resolve('Hello World');
}
}, 1000);
return dfd.promise();
}
Я хотел бы найти лучший способ сделать следующее. Обратите внимание, что это использование jQuery 1.8.x.
var promise = func1();
promise.done(function(message1) {
var promise2 = func2(message1);
promise2.done(function(message2) {
alert(message2);
});
});
Любые идеи? Я думал, что использование jQuery #pipe или #then будет работать, но я не могу понять это. Вот скрипка для игры: http://jsfiddle.net/Z7prn/
Ответы
Ответ 1
Это не так сложно (используйте .then
или .pipe
, они оба одинаковы с jQuery 1.8, я думаю).
promise.then(func2).done(function(message) {
alert(message);
});
Так как func2
возвращает новый отложенный объект, вместо него обращается обратный вызов .done
.
DEMO
Ответ 2
У меня был аналогичный вариант использования, поэтому я думаю, что это должно помочь вам.
Следующий метод примет массив методов (который может возвращать или не возвращать Promises) и выполнять их последовательно, ожидая завершения каждого отложенного до его продолжения. Поведение по умолчанию - это остановка при сбое; второй аргумент позволяет вам продолжить работу, если вызов завершился неудачно или нет.
Подписи done/fail handler (Array <context> ) Функция (Array < Object {reject | resolved: arguments} > ), где контекст является контекстом каждого разрешенияWith/rejectWith вызова или отложенного вопроса и аргументов это набор аргументов, который был передан в разрешении/отклонении.
(function ($) {
"use strict";
var copy = function (a) {
return Array.prototype.slice.call(a);
};
/**
Handle a sequence of methods, stopping on failure by default
@param Array<Function> chain List of methods to execute. Non-deferred return values will be treated as successful deferreds.
@param Boolean continueOnFailure Continue executing even if one of the returned deferreds fails.
@returns Deferred
*/
$.sequence = function (chain, continueOnFailure) {
var handleStep, handleResult,
steps = copy(chain),
def = new $.Deferred(),
defs = [],
results = [];
handleStep = function () {
if (!steps.length) {
def.resolveWith(defs, [ results ]);
return;
}
var step = steps.shift(),
result = step();
handleResult(
$.when(result).always(function () {
defs.push(this);
}).done(function () {
results.push({ resolved: copy(arguments) });
}).fail(function () {
results.push({ rejected: copy(arguments) });
})
);
};
handleResult = continueOnFailure ?
function (result) {
result.always(function () {
handleStep();
});
} :
function (result) {
result.done(handleStep)
.fail(function () {
def.rejectWith(defs, [ results ]);
});
};
handleStep();
return def.promise();
};
}(this.jQuery));
Простой пример использования: http://jsfiddle.net/rG9rA/
function func1() {
var dfd = $.Deferred();
setTimeout(function() {
dfd.resolve('Password');
}, 1000);
return dfd.promise();
}
function func2(message) {
var dfd = $.Deferred();
setTimeout(function() {
if (message == 'Password') {
dfd.resolve('Hello World');
}
}, 1000);
return dfd.promise();
}
$.sequence([func1, func2, function () { alert('done'); }]);
Ответ 3
Используйте JQuery.when(). Это именно то, что вы хотите связать массив отложенных событий и запустить функцию, когда все будет сделано.
Обновление 2017 (после просмотра downvotes):
То, что OP хотел, было лучшей версией его кода для последовательного запуска promises. Вот моя версия, используя $.when
:
function func1() {
var dfd = $.Deferred();
setTimeout(function() {
dfd.resolve('Password');
}, 1000);
return dfd.promise();
}
function func2(message) {
var dfd = $.Deferred();
setTimeout(function() {
if (message == 'Password') {
dfd.resolve('Hello World');
}
}, 1000);
return dfd.promise();
}
// ~~~~~~~~~~ using $.when here ~~~~~~~~~~~~
$.when(func1()).then(function(result1) {
$.when(func2(result1)).then(function(result2) {
alert(result2);
})
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.5.0/jquery.min.js"></script>