Интерфейс обещаний не особенно интуитивно понятный, но мощный. В этой главе мы лишь частично опишем его. Больше информации можно найти на 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
не обозначил обработчик неудач. Это допустимо. Ошибка будет передана в обещание, возвращаемое через