Друга спроба відповіді, в якій я намагаюся бути більш пояснювальною:
По-перше, деякі необхідні передумови з RSVP README :
Дійсно чудова частина виникає, коли ви повертаєте обіцянку від першого обробника ... Це дозволяє згладити вкладені зворотні виклики і є головною особливістю обіцянок, яка запобігає "дрейфу вправо" в програмах з великою кількістю асинхронного коду.
Це саме те, як ви даєте обіцянки послідовно, повертаючи пізнішу обіцянку з then
обіцянки, яка повинна закінчитись перед нею.
Корисно подумати про такий набір обіцянок, як дерево, де гілки представляють послідовні процеси, а листя - паралельні процеси.
Процес побудови такого дерева обіцянок є аналогічним найпоширенішому завданню побудови інших видів дерев: підтримуйте вказівник або посилання на те, де в дереві ви зараз додаєте гілки, та ітеративно додайте речі.
Як зазначив у своїй відповіді @Esailija, якщо у вас є масив функцій, що повертають обіцянки, які не беруть аргументи, ви можете використати reduce
для того, щоб акуратно побудувати дерево для вас. Якщо ви коли-небудь застосовували зменшення для себе, ви зрозумієте, що зменшення робиться за лаштунками у відповіді @ Esailija - це підтримка посилання на поточну обіцянку ( cur
) і наявність кожної обіцянки, що повертає наступну обіцянку у своїй then
.
Якщо у вас НЕ є приємного масиву однорідних (щодо аргументів, які вони беруть / повертають), які повертають функції, або якщо вам потрібна більш складна структура, ніж проста лінійна послідовність, ви можете побудувати дерево обіцянок самостійно, підтримуючи посилання на позицію в дереві обіцянок, де ви хочете додати нові обіцянки:
var root_promise = current_promise = Ember.Deferred.create();
current_promise = current_promise.then(function(){
return
});
current_promise = current_promise.then(function(){
return
});
root_promise.resolve();
Ви можете створювати комбінації одночасних та послідовних процесів, використовуючи RSVP.all, щоб додати декілька "листя" до обіцяної "гілки". Моя прихильна до занадто складної відповіді показує приклад цього.
Ви також можете використовувати Ember.run.scheduleOnce ('afterRender'), щоб переконатися, що щось, зроблене в одній обіцянці, буде відтворено до запуску наступної обіцянки - моя прихильна до занадто складної відповіді також показує приклад цього.