Выразительный JavaScript (Хавербеке) - страница 190

Интерфейс обещаний не особенно интуитивно понятный, но мощный. В этой главе мы лишь частично опишем его. Больше информации можно найти на www.promisejs.org.

Для создания объекта >promises мы вызываем конструктор >Promise, задавая ему функцию инициализации асинхронного действия. Конструктор вызывает эту функцию и передаёт ей два аргумента, которые сами также являются функциями. Первая должна вызываться в удачном случае, другая – в неудачном.

И вот наша обёртка для запросов >GET, которая на этот раз возвращает обещание. Теперь мы просто назовём его >get.

>function get(url) {

>  return new Promise(function(succeed, fail) {

>    var req = new XMLHttpRequest();

>    req.open("GET", url, true);

>    req.addEventListener("load", function() {

>      if (req.status < 400)

>        succeed(req.responseText);

>      else

>        fail(new Error("Request failed: " + req.statusText));

>    });

>    req.addEventListener("error", function() {

>      fail(new Error("Network error"));

>    });

>    req.send(null);

>  });

>}

Заметьте, что интерфейс к самой функции упростился. Мы передаём ей URL, а она возвращает обещание. Оно работает как обработчик для выходных данных запроса. У него есть метод >then, который вызывается с двумя функциями: одной для обработки успеха, другой – для неудачи.

>get("example/data.txt").then(function(text) {

>  console.log("data.txt: " + text);

>}, function(error) {

>  console.log("Failed to fetch data.txt: " + error);

>});

Пока это всё ещё один из способов выразить то же, что мы уже сделали. Только когда у вас появляется цепь событий, становится видна заметная разница.

Вызов >then производит новое обещание, чей результат (значение, передающееся в обработчики успешных результатов) зависит от значения, возвращаемого первой переданной нами в >then функцией. Эта функция может вернуть ещё одно обещание, обозначая что проводится дополнительная асинхронная работа. В этом случае обещание, возвращаемое >then само по себе будет ждать обещания, возвращённого функцией-обработчиком, и успех или неудача произойдут с таким же значением. Когда функция-обработчик возвращает значение, не являющееся обещанием, обещание, возвращаемое >then, становится успешным, в качестве результата используя это значение.

Значит, вы можете использовать >then для изменения результата обещания. К примеру, следующая функция возвращает обещание, чей результат – содержимое с данного URL, разобранное как JSON:

>function getJSON(url) {

>  return get(url).then(JSON.parse);

>}

Последний вызов >then не обозначил обработчик неудач. Это допустимо. Ошибка будет передана в обещание, возвращаемое через