Pull to refresh

jQuery.waterfall. Небольшая полезняшка

Reading time2 min
Views7.2K
В текущем проекте возникла необходимость выполнить последовательную серию ajax запросов и, по завершении — что-то сделать со всеми их результатами.
Довольно типовая задача, паттерн ее решения обычно называют 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)
})


Вот, собственно, и все. Критика и советы приветствуются.
Код на гитхабе
Tags:
Hubs:
+53
Comments41

Articles