Обещания (promise) представляют собой будущий результат асинхронных операций. Учитывая асинхронный контекст, значения, представленные объектами Обещания, могут быть доступны мгновенно или через некоторое время в будущем, а в других случаях они могут быть недоступны.

У Объекта new Promise(executor) при создании есть четыре внутренних свойства:

  • PromiseState – состояние, вначале «pending».
  • PromiseResult – результат, при создании значения нет.
  • PromiseFulfillReactions – список функций-обработчиков успешного выполнения.
  • PromiseRejectReactions – список функций-обработчиков ошибки.

Обещание (new Promise(executor)) может быть в любом из следующих 3 состояний (PromiseState):

  • pending: Это начальное состояние, означает, что обещание не выполнено и не отклонено.
  • fulfilled: Это означает, что обещание выполнено и находится в состоянии «выполнен успешно»
  • rejected: Это означает, что обещание выполнено и находится в состоянии «выполнен с ошибкой»

Когда функция-executor вызывает reject или resolve, то "PromiseState" становится "resolved" или "rejected", а все функции-обработчики из соответствующего списка перемещаются в специальную системную очередь "PromiseJobs".

Все функции из списка обработчиков вызываются с результатом (PromiseResult) обещания, одна за другой. Результат обещания после установки не меняется.

Допустим, имеется функция dlPage, которая возвращает промис, при успешном разрешении которого возвращается html-объект. Завернем запрос (request) в обещание:

function dlPage(url) {
  return new Promise((resolve, reject) => {
      request(url, (error, response, body) => {
          if (error) reject(error);
          if (response.statusCode != 200) {
              reject('Invalid status code <' + response.statusCode + '>');
          }
          resolve(body);
      });
  });
}

Попробуем функцию вызвать, вывести в лог html-объект:

function myFunction() {
  dlPage('http://phomka.ru')
    .then(
      result => {
        console.log(html)
      }
      error => {
        console.error("ошибка: " + error); // error - аргумент reject

      }
    )
}

С начиная с версии 7.6 в Node.js можно использовать новый способ написания асинхронного кода, используя async и await.

В основе конструкции async/await лежат промисы. Нужно учитывать, что этот механизм нельзя использовать с коллбэками.

Конструкции async/await, как и промисы, не блокируют главный поток выполнения программы.

Благодаря async/await, асинхронный код становится похожим на синхронный.

Ниже приведен пример, использующий асинхронную функцию и ждущий обещания (Promise) функции dlPage (приведенной выше):

async function myFunction() {
  try {
      const html = await dlPage('http://phomka.ru');
      console.log(html);
  } catch (error) {
      console.error(error);
  }
}

Запустить асинхронную функцию

myFunction();

Запись await dlPage() означает, что вызов console.log(html) будет ожидать разрешения промиса dlPage(), после чего выведет то, что возвратит функция.