Вторая попытка ответа на который я стараюсь быть более описательный:
Во-первых, некоторый требуемый фон, от RSVP README:
Действительно удивительная часть приходит, когда вы возвращаете обещание от первого обработчика ... Это позволяет сгладить вложенные обратные вызовы и является основной особенностью обещаний, которые предотвращают «правый дрейф» в программах с большим количеством асинхронного кода ,
Именно так вы выполняете обещания последовательно, возвращая позднее обещание от then
обещания, которое должно было закончить перед ним.
Полезно подумать о таком наборе обещаний, как дерево, где ветви представляют собой последовательные процессы, а листья представляют собой параллельные процессы.
Процесс создания такого дерева обещаний аналогичен самой общей задаче построения других видов деревьев: поддерживать указатель или ссылку на то, где в дереве, которое вы в настоящее время добавляете ветви, и итеративно добавляете вещи.
Как отметил в своем ответе @Esailija, если у вас есть множество функций, возвращающих обещание, которые не принимают аргументы, вы можете использовать reduce
, чтобы аккуратно построить дерево для вас. Если вы когда-либо реализовали сокращение для себя, вы поймете, что то, что сокращение делает за кулисами в ответе @ Esailija, поддерживает ссылку на текущее обещание (cur
), и каждое обещание возвращает следующее обещание в его then
.
Если у вас нет хорошего массива однородных (по отношению к аргументам, которые они принимают/возвращают) обещают возвращающие функции, или если вам нужна более сложная структура, чем простая линейная последовательность, вы можете построить дерево обещает себе, сохраняя ссылку на положение в дереве обещание, где вы хотите добавить новые обещания:
var root_promise = current_promise = Ember.Deferred.create();
// you can also just use your first real promise as the root; the advantage of
// using an empty one is in the case where the process of BUILDING your tree of
// promises is also asynchronous and you need to make sure it is built first
// before starting it
current_promise = current_promise.then(function(){
return // ...something that returns a promise...;
});
current_promise = current_promise.then(function(){
return // ...something that returns a promise...;
});
// etc.
root_promise.resolve();
вы можете создавать комбинации параллельных и последовательных процессов с использованием RSVP.all для добавления нескольких «листья» к обещать «ветвь». Примером этого может служить мой слишком сложный ответ.
Вы также можете использовать Ember.run.scheduleOnce ('afterRender'), чтобы гарантировать, что что-то сделанное с помощью одного обещания будет выдано до того, как будет запущено следующее обещание - мой ответ слишком сложный для слишком сложного ответа также показывает пример этого.
из других ответов и нисходящих комментариев по моему, кажется, что больше людей нужно читать [rsvp README] (https://github.com/tildeio/rsvp.js?utm_source=javascriptweekly), где объясняется «Действительно потрясающий часть приходит, когда вы возвращаете обещание от первого обработчика ». Если вы этого не делаете, вы действительно упускаете выразительную силу обещаний. –
Подобный вопрос, но не относящийся к структуре: http://stackoverflow.com/q/24586110/245966 –