JavaScript метод Promise.then()

JavaScript Promise

Определение и применение

JavaScript метод .then()ECMAScript 2015 объекта Promise добавляет обработчик, или обработчики, вызываемые когда объект Promise имеет состояние fulfilled (успешное выполнение), или rejected (выполнение отклонено).

Поддержка браузерами

МетодChrome
Chrome
Firefox
Firefox
Opera
Opera
Safari
Safari
Internet Explorer
IExplorer
Microsoft Edge
Edge
.then()ECMAScript 201532.029.019.08.0НетДа

JavaScript синтаксис:

p.then(onFulfilled);
p.then(onFulfilled, onRejected);

onFulfilled - Function
onRejected - Function

После выполнения или отклонения обещания соответствующая функция обработчика (onFulfilled, или onRejected) будет вызвана асинхронно (запланирована в текущем цикле потока). Поведение функции обработчика соответствует определенному набору правил. Если функция обработчика:

Спецификация

ECMAScript 2015 (6th Edition, ECMA-262)

Значения параметров

ПараметрОписание
onFulfilledФункция, которая будет вызвана, когда обещание выполнено. Эта функция имеет только один аргумент - значение с которым обещание было выполнено. Если это не функция, она внутренне заменяется функцией "Identity" (возвращает полученный аргумент).
onRejectedФункция, которая будет вызвана, когда обещание отклонено. Эта функция имеет только один аргумент - значение с которым обещание было отклонено. Если это не функция, она внутренне заменяется функцией "Thrower" (она выдает ошибку, полученную в качестве аргумента). Необязательный аргумент.

Пример использования

Базовое использование обрабочиков

const promise = Promise.resolve("Успешно"); // обещание успешно выполнено с заданным значением
const promise2 = Promise.reject(new Error("Отклонено")); // обещание отклонено с заданным значением

promise.then(function(value) { // Если успешно выполнен (fulfilled)
  console.log(value); 
}, function (reason) { // Если завершился ошибкой (rejected)
  console.log(reason); 
});

// Успешно

// использование стрелочной функции
promise2.then( val => console.log(elem), // обработчик для успешного выполнения
                            reason => console.log(reason.message)); // обработчик при отклоненном выполнении

// Отклонено

В этом примере мы инициализировали две переменные, которые содержат объект Promise, в первом случае с использованием метода resolve()ECMAScript 2015 обещание было успешно выполнено с заданным значением, а во втором с использованием метода reject()ECMAScript 2015 отклонено.

С использованием метода then()ECMAScript 2015 мы добавили обработчики, вызываемые когда объект Promise имеет состояние fulfilled (успешное выполнение), или rejected (выполнение отклонено). В первом случае будет срабатывать обработчик для успешного выполнения, а во втором обработчик при отклоненном выполнении.

Составление цепных вызовов

В следующем примере мы рассмотрим с Вами как составлять цепочки вызовов с использованием метода then()ECMAScript 2015:

const promise = Promise.resolve(1); // обещание успешно выполнено с заданным значением

promise.then(val => {val = val + 1; console.log(val); return val}) // обработчик для успешного выполнения
              .then(val => {val = val + 1; console.log(val); return val}) // обработчик для успешного выполнения
              .then(val => {val = val + 1; console.log(val); return val}) // обработчик для успешного выполнения

// 2
// 3
// 4

В этом примере мы инициализировали переменную, которая содержит объект Promise, который мы вернули с использованием метода resolve()ECMAScript 2015 (обещание было успешно выполнено с заданным значением).

С использованием метода then()ECMAScript 2015 мы добавили обработчики, вызываемые когда объект Promise имеет состояние fulfilled (успешное выполнение). Обратите внимание, что при каждом последующем вызове метода then()ECMAScript 2015 передается новое значение (увеличиваем переданное значение из предыдущего вызова на единицу), в результате чего в консоль будут выведены три значения - 2, 3 и 4.

Обработка ошибок в обработчиках

В следудующем примере мы с Вами рассмотрим ситуацию при которой в вызове обработчика, предназначенного для обработки состояния fulfilled (успешное выполнение) объекта Promise происходит ошибка:

const promise = Promise.resolve(); // обещание успешно выполнено с заданным значением
promise.then(() => {throw new Error("Ошибочка вышла")}) // генерируем исключение и возвращаем отклоненное обещание
               .then( val => console.log( val ), // обработчик не будет вызван
                           err => console.log( err.message )); // обработчик при отклоненном выполнении

// Ошибочка вышла

В этом примере мы инициализировали переменную, которая содержит объект Promise, который мы вернули с использованием метода resolve()ECMAScript 2015 (обещание было успешно выполнено с заданным значением). С использованием методов then()ECMAScript 2015 мы добавили цепочку вызовов.

Обратите внимание, что внутри первого вызова метода then()ECMAScript 2015 мы генерируем исключение с определенном текстом ошибки. Что приводит к тому, что мы возвращаем объект Promise выполнение которого было отклонено. В результате следующий вызов метода then()ECMAScript 2015 будет обрабатывать ошибку, то есть сработает функция, которая предназначена для случая, когда обещание отклонено (второй аргумент).

На практике, как правило, для удобства и лучшей читаемости кода при обработке ошибок используют метод catch()ECMAScript 2015, а не используют синтаксис метода then()ECMAScript 2015 с двумя аргументами. Рассмотрим следующий пример:

const promise = Promise.resolve(); // обещание успешно выполнено с заданным значением

promise.then(() => {throw new Error("Ошибочка вышла")}) // генерируем исключение и возвращаем отклоненное обещание
              .catch(error => console.log(error.message)) // добавляем обработчик для отклоненного обещания
              .then(() => console.log("Обработчик будет вызван" )); // обработчик для успешного выполнения
  
// Ошибочка вышла
// Обработчик будет вызван

В этом примере мы инициализировали переменную, которая содержит объект Promise, который мы вернули с использованием метода resolve()ECMAScript 2015 (обещание было успешно выполнено).

С использованием метода then()ECMAScript 2015 мы добавили обработчик, вызываемый когда объект Promise имеет состояние fulfilled (успешное выполнение). Внутри него мы генерируем исключение с определенным текстом ошибки, что приводит к тому, что мы возвращаем объект Promise выполнение которого было отклонено.

Обратите внимание, что далее для обработки ошибки мы используем метод catch()ECMAScript 2015, а не используем синтаксис метода then()ECMAScript 2015 с двумя аргументами. Метод catch()ECMAScript 2015 является сокращенным вариантом метода then(undefined, onRejected).

Обратите внимание, что не смотря на то что мы обработали отклоненное обещание внутри метода catch()ECMAScript 2015, следующий за ним метод then()ECMAScript 2015 будет срабатывать как для обещания, которое было успешно выполнено (сработает функция из первого аргумента), так как функция обработчик метода catch()ECMAScript 2015 не выдает ошибку, или возвращает обещание, которое само по себе отвергается.

В следующем примере мы рассмотрим ситуацию в которой метод catch()ECMAScript 2015 будет генерировать исключение:

const promise = Promise.reject(new Error("Ошибочка")); // обещание отклонено

promise.catch(error => { // добавляем обработчик для отклоненного обещания
  console.log(error.message);  // выводит в консоль текст ошибки
  throw new Error("Ошибочка 2"); // генерируем исключение и возвращаем отклоненное обещание
}).catch(error => { // добавляем обработчик для отклоненного обещания
  console.log(error.message); // выводит в консоль текст ошибки
  throw new Error("Ошибочка 3");// генерируем исключение и возвращаем отклоненное обещание
}).catch(error => console.log(error.message)) // добавляем обработчик для отклоненного обещания и выводим в консоль текст ошибки
  .then(() => console.log("Наконец без ошибок" )); // обработчик для успешного выполнения
  
// Ошибочка
// Ошибочка 2
// Ошибочка 3
// Наконец без ошибок

В этом примере мы инициализировали переменную, которая содержит объект Promise, который мы вернули с использованием метода reject()ECMAScript 2015 (обещание было отклонено).

Для обработки ошибок мы используем цепочку вызовов, которую мы составили с использованием метода catch()ECMAScript 2015. Обратите внимание, что первые два вызова метода catch()ECMAScript 2015 помимо того, что выводят в консоль текст ошибки, дополнительно еще генерируют исключение.

Третий метод catch()ECMAScript 2015 просто выводит в консоль текст ошибки и возвращает обещание, которое имеет состояние fulfilled (успешное выполнение), которое мы и обрабатываем в методе then()ECMAScript 2015, который находится в конце цепочки.

Нюансы асинхронного выполнения

В следующих примерах мы рассмотрим нюансы асинхронного выполнения при использовании цепных методов then()ECMAScript 2015:

const promise = Promise.resolve("hello"); // обещание успешно выполнено с заданным значением

promise.then(function(val) { // обработчик для успешного выполнения
  return new Promise(function(resolve, reject) { // возвращаем новое обещание
      setTimeout(function() { // вызываем функцию через указанное число миллисекунд
        val += " world"; // изменяем полученное значение
        console.log(1, val); // выводим значение в консоль
        resolve(val); // изменяем состояние обещания на fulfilled (успешное выполнение)
      }, 1000);
    });
  })
  .then(function(val) { // обработчик для успешного выполнения
    setTimeout(function() { // вызываем функцию через указанное число миллисекунд
      val += " !!!"; // изменяем полученное значение
      console.log(2, val); // выводим значение в консоль
    }, 1000)
    return val; // возвращаем значение
  })
  .then(function(val) { // обработчик для успешного выполнения
    console.log(3, val); // выводим значение в консоль
  });

// 1 "hello world"
// 3 "hello world"
// 2 "hello world !!!"

В этом примере мы инициализировали переменную, которая содержит объект Promise, который мы вернули с использованием метода resolve()ECMAScript 2015 (обещание было успешно выполнено). С использованием метода then()ECMAScript 2015 мы добавили обработчики, вызываемые когда объект Promise имеет состояние fulfilled (успешное выполнение).

Внутри первого обработчика then()ECMAScript 2015 мы возвращаем новое обещание, которое с использованием функции setTimeout() через одну секунду вызовет метод resolve()ECMAScript 2015, который вернет обещание, которое было успешно выполнено.

Следующий метод then()ECMAScript 2015 принимает переданное значение, с использованием функции setTimeout() через одну секунду изменяет это значение, выведет это значение в консоль, и возвратит это значение. Здесь и кроется главный нюанс асинхронного выполнения, полученное значение будет передано сразу в следующий обработчик не дожидаясь завершения выполнения функции setTimeout(), которая изменяет впоследствии это значение.

Последний обработчик then()ECMAScript 2015 просто выводит в консоль полученное значение. В следующем примере мы рассмотрим как вывести значение по порядку:

const promise = Promise.resolve("hello"); // обещание успешно выполнено с заданным значением

promise.then(function(val) { // обработчик для успешного выполнения
  return new Promise(function(resolve, reject) { // возвращаем новое обещание
      setTimeout(function() { // вызываем функцию через указанное число миллисекунд
        val += " world"; // изменяем полученное значение
        console.log(1, val); // выводим значение в консоль
        resolve(val); // изменяем состояние обещания на fulfilled (успешное выполнение)
      }, 1000);
    });
  })
  .then(function(val) { // обработчик для успешного выполнения
    return new Promise(function(resolve, reject) { // возвращаем новое обещание
      setTimeout(function() { // вызываем функцию через указанное число миллисекунд
        val += " !!!"; // изменяем полученное значение
        console.log(2, val); // выводим значение в консоль
        resolve(val); // изменяем состояние обещания на fulfilled (успешное выполнение)
      }, 1000);
    });
  })
  .then(function(val) { // обработчик для успешного выполнения
    console.log(3, val); // выводим значение в консоль
  });

// 1 "hello world"
// 2 "hello world !!!"
// 3 "hello world !!!"

По аналогии с предыдущим примером мы инициализировали переменную, которая содержит объект Promise, который мы вернули с использованием метода resolve()ECMAScript 2015 (обещание было успешно выполнено), и с использованием метода then()ECMAScript 2015 добавили обработчики.

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

JavaScript Promise
×

Кажется, вы используете блокировщик рекламы :(

Этот ресурс не является коммерческим проектом и развивается на энтузиазме автора сайта, который посвящает все свое свободное время этому проекту.

Добавьте, пожалуйста, basicweb.ru в исключения блокировщика рекламы, этим вы поможете развитию проекта.