Перевод не завершен. Пожалуйста, помогите перевести эту статью с английского.

Promise (промис, англ. "обещание") - это объект, представляющий результат - успешное или неудачное завершение - асинхронной операции. Промис может быть создан при помощи конструктора. Хотя большиство людей используют уже созданные промисы, возвращаемые функциями. Поэтому в этом руководстве сперва будут рассмотрены затраты ресурсов при возвращении промисов.

В сущности, промис - это возвращаемый объект, в который вы записываете два коллбэка, вместо того, чтобы передать их функции.

Например, вместо старомодной функции, которая принимает два коллбэка и вызывает один из них в зависимости от успешного или неудачного завершения операции:

function successCallback(result) {
  console.log("Успешное завершение:" + result);
}

function failureCallback(error) {
  console.log("Неудача по причине " + error);
}

doSomething(successCallback, failureCallback);

…современные функции возвращают промис, в который вы записываете ваши коллбэки:

let promise = doSomething(); 
promise.then(successCallback, failureCallback);

…или просто:

doSomething().then(successCallback, failureCallback);

Мы называем это асинхронным вызовом функции. У этого соглашения есть нескоолько преимуществ. Давайте рассмотрим их.

Гарантии

В отличие от старомодных переданных коллбэков, промис дает некоторые гарантии:

  • Коллбэки никогда не будут вызваны до завершения обработки текущего события в событийном цикле JavaScript.
  • Коллбеки, добавленные через .then, будут вызваны даже после успешного или неудачного завершения асинхронной операции.
  • Несколько коллбэков может быть добавлено вызовом .then нужное количество раз, и они будут выполняться независимо по порядку.

Но наиболее непосредственная польза от промисов - цепочка вызовов (chaining).

Цепочка вызовов

Общая нужда - выполнять две или более асинхронных операции одна за другой, причём каждая следующая начинается при успешном завершении предыдущей и использует результат её выполнения. Мы реализуем это, создавая цепочку вызовов промисов (promise chain).

Вот в чём магия: функция then возвращает новый промис, отличяющийся от первоначального:

let promise = doSomething();
let promise2 = promise.then(successCallback, failureCallback);

или

let promise2 = doSomething().then(successCallback, failureCallback);

Второй промис представляет завершение не только doSomething(), но и функций successCallback или failureCallback, переданных вами, а они тоже могут быть асинхронными функциями, возвращающими промис. В этом случае все коллбэки, добавленные к promise2 будут поставлены в очередь за промисом, возвращаемым successCallback или failureCallback.

По сути, каждый вызванный промис означает успешное завершение предыдущих шагов в цепочке.

Раньше выполнение нескольких асинхронных операций друг за другом приводило к классической "Вавилонской башне" коллбэков:

doSomething(function(result) {
  doSomethingElse(result, function(newResult) {
    doThirdThing(newResult, function(finalResult) {
      console.log('Итоговый результат: ' + finalResult);
    }, failureCallback);
  }, failureCallback);
}, failureCallback);

В современных функциях мы записываем коллбэки в возвращаемые промисы - формируем цепочку промисов:

doSomething().then(function(result) {
  return doSomethingElse(result);
})
.then(function(newResult) {
  return doThirdThing(newResult);
})
.then(function(finalResult) {
  console.log('Итоговый результат: ' + finalResult);
})
.catch(failureCallback);

Аргументы then необязательны, а catch(failureCallback) - это сокращение для then(null, failureCallback). Вот как это выражено с помощью стрелочных функций:

doSomething()
.then(result => doSomethingElse(result))
.then(newResult => doThirdThing(newResult))
.then(finalResult => {
  console.log(`Итоговый результат: ${finalResult}`);
})
.catch(failureCallback);

Важно: Всегда возвращайте промисы в return, иначе коллбэки небудут сцеплены и могут ошибки могут быть не пойманы (стрелочные функции неявно возвращают результат, если скобки {} вокруг тела функции опущены).

Смотрите также

Метки документа и участники

 Внесли вклад в эту страницу: Geloosa
 Обновлялась последний раз: Geloosa,