Цепочки обработчиков в JS Promise |
Promise — это относительно новая фича JavaScript-а, позволяющая выполнять отложенные действия — то, что раньше решалось коллбэками. Хорошее введение в эту технологию есть на сайте HTML5Rocks, не буду его пересказывать.
У Promise есть два (интересующих нас сейчас) метода — .then()
и .catch()
, в которые передаются функции-обработчики для состояний "выполнено" (fulfilled) и "отказ" (rejected) соответственно. Эти методы можно объединять в цепочки: prom.then().then().catch().then().catch().catch().…
. Вопрос: в каком порядке вызываются эти обработчики, что они получают, и от чего всё это вообще зависит?
Для начала посмотрим на конструкцию prom.then().then()
(здесь prom
— это некоторый Promise). Что такое тут prom.then()
? Очевидно, это Promise, раз у него есть методы .then()
и .catch()
. Каково значение этого Promise? "Естественным" может показаться предположение, что это тот же самый prom
передаётся по цепочке, но на самом деле это не так (и хорошо, что не так).
Каждый обработчик .then()
и .catch()
возвращает какое-то значение. Даже если функция не возвращает значение явно, то результатом её всё равно является значение undefined
. Далее действуют правила:
Promise.resolve(…)
и становится Promise-ом в выполненном состоянии;Promise.reject(…)
и становится Promise-ом в состоянии отказа.Самое полезное применение этих правил — возможность обработки данных в цепочке. Например, так:
get('data.json')
.then(function(response) {
// response — текстовые данные
return JSON.parse(response);
})
.then(function(response) {
// а тут уже response — объект, полученный в предыдущем обработчике
console.log("Yey JSON!", response);
});
Но вернёмся к произвольным цепочкам. У нас есть Promise, в зависимости от его состояния, он вызывает .then()
или .catch()
, ближайшие к нему по цепочке. Вызванный обработчик возвращает новый Promise, который снова вызывает .then()
или .catch()
, ближайшие по цепочке. И так далее.
Приведём пример (писать буду в ES6-синтаксисе, он проще):
Promise.reject("A")
.then(x => { console.log("THEN1", x); })
.catch(x => { console.log("CATCH1", x); })
.then(x => { console.log("THEN2", x); })
.catch(x => { console.log("CATCH2", x); });
Что мы получим в консоли? Вот что:
CATCH1 A
THEN2 undefined
Почему так? У нас есть Promise в состоянии "отказ", значит, он вызовет ближайший обработчик .catch()
в цепочке, это CATCH1. Этот обработчик не возвращает ничего (т. е. возвращает undefined
), значит, на выходе из него мы получаем выполненный Promise со значением undefined
. Выполненый Promise вызывает ближайший к нему .then()
, это THEN2.
Ещё пример:
Promise.reject("A")
.catch(x => {
console.log("CATCH1", x);
return Promise.reject("B");
})
.then(x => { console.log("THEN1", x); })
.catch(x => { console.log("CATCH2", x); })
.then(x => { console.log("THEN2", x); });
Результат (посчитайте сами, почему именно так):
CATCH1 A
CATCH2 B
THEN2 undefined
Этот пост в блоге POST /blog (13:08 30.08.2015)
Комментировать | « Пред. запись — К дневнику — След. запись » | Страницы: [1] [Новые] |