Асинхронное программирование в JavaScript. Использование Deferred и Promise. - Блог ITVDN
ITVDN: курсы программирования
Видеокурсы по
программированию

    Выбери свою IT специальность

    Подписка

    Выбери свою IT специальность

    Подписка

      Асинхронное программирование в JavaScript. Использование Deferred и Promise.

      advertisement advertisement

      Введение

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


      Асинхронное программирование в JavaScript

      Асинхронное программирование в JavaScript не связано с многопоточностью. JavaScript – однопоточный, это означает, что не существует стандартных языковых конструкций, которые позволят создать в приложении дополнительный поток для выполнения параллельных вычислений (единственная возможность организовать настоящую многопоточность – использовать Web Workers). Асинхронное программирование – стиль программирования, при котором результат работы функций доступен не сразу, а через некоторое время. Асинхронная функция – это функция, после вызова которой JavaScript приложение продолжает работать, потому что функция сразу выполняет возврат. Результат работы асинхронной функции становится известным позже, и для того, чтобы оповестить наше приложении о полученных значениях, асинхронная функция вызывает другую функцию (callback), которую мы передаем в аргументах при запуске.

      Например, getDataFromServer(onSuccess); getDataFromServer – асинхронная функция, выполняющая запрос на сервер, onSuccess – callback функция или функция обратного вызова, которая запускается при успешном завершении операции обращения к серверу.

      Использование callback функций может привести к появлению проблемы, которую называют Pyramid of Doom – callback функция, в которой вызывается асинхронная функция, которой передается callback функция, и в ней же вызывается асинхронная функция и т.д.

      step1(function(result1) {

             step2(function(result2) {

                   step3(function(result3) {

                          // и т.д.

                   });

             });

      });

      Такой код тяжело читать и сопровождать. Для того, чтобы подобных проблем не было , мы можем использовать различные шаблоны для организации кода. Один из таких шаблонов - Promise. (Другие варианты организации асинхронного кода можно посмотреть в этой статье)

      Что такое Promise (ECMAScript 6)

      Promise – прокси объект, который представляет еще не известное значение (значение будет доступно после завершения асинхронной операции). С Promise можно ассоциировать две функции: первая - для выполнения операции, если асинхронная задача завершилась успешно. И вторая - для операции в случае ошибки.

      Promise может находиться в одном из трех состояний:

      • pending;
      • fulfilled;
      • rejected.

      Например, мы выполняем AJAX запрос с помощью асинхронной функции, которая возвращает Promise. Как только мы выполним запрос, функция создаст Promise, который будет в состоянии pending. Когда сервер вернет ответ, Promise перейдет в состояние fulfilled, если ответ был 200 OK, или в состояние rejected, если статус код был 500 Internal Server Error (или другой код ошибки). При переходе в fullfiled состояние Promise будет содержать ответ от сервера, при переходе в rejected – ошибку или текст ошибки (все зависит от реализации асинхронной функции).

      Как только Promise меняет свое состояние, запускается функция, которая была зарегистрирована как реакция на соответствующее состояние.

      Пример использования асинхронной функции download, которая возвращает Promise:

      download("data.txt").then(function (data) {

          console.log(data);

      }, function (error) {

          console.error(error);

      });

      или такая запись

      var p = download("data.txt");

      p.then(onFulfilled, onRejected);

      function onFulfilled(data) {

          console.log(data);

      }

      function onRejected(error) {

          console.error(error);

      }

      Для того, чтобы установить, что произойдет после завершения асинхронной операции, на объекте Promise необходимо вызвать метод then. Этот метод принимает два аргумента:

      1. обработчик для состояния fulfilled
      2. обработчик для состояния rejected

      Функцию then можно вызвать в любой момент, даже если асинхронная операция уже завершена и Promise перешел из состояния pending. Если вызвать then на Promise, который уже находится в конкретном состоянии, то будет вызвана соответствующая состоянию функция, переданная в метод then.

      Ниже приведен код асинхронной функции download.

      function download(url) {

          // Создание нового объекта Promise

          return new Promise(function (resolve, reject) {

              var req = new XMLHttpRequest();

              req.open('GET', url);

              req.onload = function () {

                  if (req.status == 200) {

                      // перевод Promise в состояние fulfilled.

                      // req.response - данные доступные в функции-обработчике

                      // перехода состояния

                      resolve(req.response);

                  }

                  else {

                      // перевод Promise в состояние rejected

                      reject(Error(req.statusText));

                  }

              };

              // Обработка сетевых ошибок

              req.onerror = function () {

                  // перевод Promise в состояние rejected

                  reject(Error("Network Error"));

              };

              // отправка запроса на сервер

              req.send();

          });

      }

      Поддержка Promise браузерами http://caniuse.com/#search=Promise

      Библиотеки для работы с Promise

      Есть много различных библиотек, которые реализуют спецификацию объекта Promise. Поэтому проблему слабой поддержки Promise ECMAScript 6 можно решить, применив одну из следующих библиотек:

      jQuery http://jquery.com/

      Q https://github.com/kriskowal/q

      When https://github.com/cujojs/when

      WinJs http://msdn.microsoft.com/en-us/library/windows/apps/br211867.aspx

      RSVP.js https://github.com/tildeio/rsvp.js

      КОММЕНТАРИИ И ОБСУЖДЕНИЯ
      advertisement advertisement

      Покупай подпискус доступом ко всем курсам и сервисам

      Библиотека современных IT знаний в удобном формате

      Выбирай свой вариант подписки в зависимости от задач, стоящих перед тобой. Но если нужно пройти полное обучение с нуля до уровня специалиста, то лучше выбирать Базовый или Премиум. А для того чтобы изучить 2-3 новые технологии, или повторить знания, готовясь к собеседованию, подойдет Пакет Стартовый.

      Стартовый
      • Все видеокурсы на 3 месяца
      • Тестирование по 10 курсам
      • Проверка 5 домашних заданий
      • Консультация с тренером 30 мин
      59.99 $
      Оформить подписку
      Премиум Plus
      • Все видеокурсы на 1 год
      • Тестирование по 24 курсам
      • Проверка 20 домашних заданий
      • Консультация с тренером 120 мин
      • Скачивание видео уроков
      120.00 $
      199.99 $
      Оформить подписку
      Акция
      Базовый
      • Все видеокурсы на 6 месяцев
      • Тестирование по 16 курсам
      • Проверка 10 домашних заданий
      • Консультация с тренером 60 мин
      89.99 $
      Оформить подписку
      Notification success
      Мы используем cookie-файлы, чтобы сделать взаимодействие с нашими веб-сайтами и услугами простым и значимым.