ITVDN logo
Видеокурсы по
программированию

Доступ более чем к 7700 видеоурокам от $19.99

Подписка
ITVDN logo
Видеокурсы по
программированию

Доступ более чем к 7700 видеоурокам от $19.99

Подписка

Введение

В современном 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

СТАТЬИ ПО СХОЖЕЙ ТЕМАТИКЕ
ВИДЕО КУРСЫ ПО СХОЖЕЙ ТЕМАТИКЕ

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

ОЦЕНИТЕ ДАННЫЙ МАТЕРИАЛ

ПОДПИСКА НА ITVDN ВЫГОДА ДО 29.95$ НА ОБУЧЕНИЕ ПРЕСТИЖНЫМ ПРОФЕССИЯМ!

1 месяц19.99$
подписка

легкий старт в обучении

3 месяца49.99$
подписка

выгода от подписки до9.98$

6 месяцев89.99$
подписка

выгода от подписки до29.95$