В метод $.when() можно передать массив объектов Deferred, так и реализуются очереди из Deferreds. Пример применения: цепочка последов-ных AJAX запросов. Когда-то у меня была примерно такая задача, и это решение я нашел на stackoverflow: 1, 2. Но к сожалению оно мне не помогло, т.к. моя задача была сложнее (последов-ть запросов могла в любой момент, как прерваться по условию, так и увеличиться).
В конце концов из-за нехватки времени пришлось использ-ть рекурсию (хотя мне хотелось реализовать это через Deferreds).
Мне это известно, но это не решает проблемы асинхронного выполнения набора Deferred объектов, переданных в $.when — он станет .done() как только все Deferred-ы будут .done.
В моей реализации следующий Deferred в цепочке выполнится только после .done() текущего — соблюдается порядок очереди. Такой себе waterfall, но натянутый на интерфейс each, вместо набора аргументов.
Именно, в этом и вся проблема. Аргументы $.when выполняются без соблюдения очереди. Единственная очередь в этом случае — результаты каждого Deferred-а будут переданы в общий .done() строго в порядке их добавления в $.when.
Убедили. Выходит, тот товарищ с stackoverflow был неправ. А я ему поверил… Хорошо, что старая добрая рекурсия меня не подвела)
А может ли ваш плагин решить мою задачу? Объясню ее подробнее: имеем массив url'ов, по к-ым делаем цепочку ajax запросов. После каждого запроса делается некоторая проверка, после которой с цепочкой запросов могут произойти изменения: она может прерваться (остановиться), либо в нее может добавлен еще один запрос.
Во-первых, .each принимает готовый массив, дальнейшие операции с ним в рамках цикла невозможны (если только не переписать реализацию).
Во-вторых, как вы заметили — у меня никак не обрабатываются .reject()-ы. Я предполагаю, что код итерации сам должен/умеет справляться со своими фейлами. В моем случае мне нужен только .resolve(), чтобы цикл мог перейти к следующей итерации.
Хотя, возможно это чревато — если итерация вернет .reject(), мой цикл никогда не закончится.
С недавних пор, кстати, в Deferred-ах появился .pipe, который, фактически, реализует синхронность, но в коде выглядит довольно сумбурно — читать очень непросто.
eachDeferred — отложенная обработка коллекции, one by one