![](https://habrastorage.org/storage/232d6e00/8bcbda9c/16462164/16b84130.jpg)
Довольно типовая задача, паттерн ее решения обычно называют waterfall (водопад). Реализации этого паттерна есть для node.js, хотя некоторые работают и в браузере — async.
Но включать целый модуль ради одного метода не хотелось. Copy/paste тоже не стал делать, но по соображениям скорее эстетическим. В async в метод передается функция обратного вызова, у нас же везде используется jQuery.Deferred. Разницы, конечно, никакой, но «ломать» стиль проекта мое «чувство прекрасного» мне не позволило :)
В результате написал небольшую утилитку по аналогии с jQuery.when
В отличии от jQuery.when аргументами надо передавать не jqxhr, а функции, их возвращающие, иначе теряется смысл водопада. Хотя ошибки это не вызовет, поскольку waterfall принимает любые типы аргументов.
Использовать ее просто.
1. Выполним по очереди 3 запроса и покажем результаты:
$.waterfall(
function() {
return $.ajax(...)
},
function(arg1) {
return $.ajax(...)
},
function(arg2) {
return $.ajax(...)
}
)
.fail(function(error) {
console.log('fail');
console.log(error);
})
.done(function() {
console.log('success');
console.log(arguments);
})
2. Выполним один запрос, проверим, что он вернул и решим, что делать дальше:
$.waterfall(
function() {
return $.ajax(...)
},
function(arg1) {
return arg1 && arg1.answer == 42 ? $.ajax(...) : false;
},
function(arg2) {
return $.ajax(...)
}
)
.fail(function(error) {
console.log('fail');
console.log(error)
})
.done(function() {
console.log('success');
console.log(arguments)
})
3. waterfall может принимать любые типы аргументов. false немедленно прервет водопад, остальные значения отличные от функций и deferred объектов будут просто добавлены в результат:
var dfrd = $.Deferred();
$.waterfall(
function() {
return $.ajax(...)
},
$.ajax(...), // будет выполнен "вне очереди"
dfrd, // серия не закончится пока вручную не сделаем resolve/reject
'string',
42,
false // серия всегда завершится ошибкой
)
.fail(function(error) {
console.log('fail');
console.log(error)
})
.done(function() {
console.log('success');
console.log(arguments)
})
Вот, собственно, и все. Критика и советы приветствуются.
Код на гитхабе