SlideShare a Scribd company logo
Михаил Давыдов - JavaScript. Асинхронность
JavaScript
Асинхронность

Михаил Давыдов
Разработчик JavaScript
Задача




    •  Качаем 1 файл
    •  После отправляем данные на 2 сервера
    •  Синхронизируемся




3
Синхронный код
    Сделаем обертку над XMLHttpRequest


     function syncXHR(method, url, data) {
         var xhr = new XMLHttpRequest();

         xhr.open(method, url, false);
         xhr.send(data);

         return xhr.responseText;
     }


     var data = syncXHR('GET', 'http://host1/page.json');
     data = processData(data);

     syncXHR('POST', 'http://host2/result/', data);
     syncXHR('POST', 'http://host3/result/', data);
     alert('Done!');


4
Схема загрузки


    Подготовка            Обработка                Отправка                Алерт


             Блокировка               Блокировка              Блокировка




                 Запрос                 Запрос                  Запрос




5
                                                                           время
Асинхронный код
    Сделаем обертку над XMLHttpRequest


     function asyncXHR(method, url, data, callback) {
         var xhr = new XMLHttpRequest();

         xhr.open(method, url, true);

         xhr.onreadystatechange = function () {
             if (xhr.readyState === 4) {
                 if (xhr.status === 200) {
                     callback(null, xhr.responseText);
                 } else {
                     callback(‘error’);
                 }
             }
         }

         xhr.send(data);
     }

6
Асинхронный код
    Сам код. Изменилось все.

     asyncXHR ('GET', ‘http://host1/page.json’, null,
     function (err, data) {
         data = processData(data);
         var counter = 2;

            function done(err, data) {
                counter--;
                if (!counter) alert(‘Done!’);
            }

           asyncXHR(‘POST’, ‘http://host2/result/’, data, done);
           asyncXHR(‘POST’, ‘http://host3/result/’, data, done);
     });




7
Схема загрузки



      Подготовка             Обработка Отправка              Алерт

                   Ожидание                       Ожидание




                    Запрос




8
                                                                     время
Где применяется "асинхронность"


    •  Производительность
    •  Интерфейс пользователя
    •  Проблемы
     –  Много лишнего шума
     –  Проблема синхронизации
     –  Куча вложенных колбэков: Pyramid of Doom

    •  Несколько реализаций
     –  Event Loop




9
Основа – Event Loop


     •  Основа всех событийных систем
     •  Использует очередь событий
     •  Ждет события
     •  Выполняет события из очереди
      –  События в очередь поступают во время выполнения событий
      –  События генерируют события

     •  Завершается когда очередь пуста


10
Паттерны

Callback,
Event,
Promise,
Deferred
Callback
     Типичный пример – обертка над XMLHttpRequest


      function asyncXHR(method, url, data, callback) {
          var xhr = new XMLHttpRequest();

           xhr.open(method, url, true);

           xhr.onreadystatechange = function () {
               if (xhr.readyState === 4) {
                   if (xhr.status === 200) {
                       callback(null, xhr.responseText);
                   } else {
                       callback(‘error’);
                   }
               }
           }

           xhr.send(data);
      }

12
Callback




     •  Самый простой вариант
      –  Дешевая абстракция

     •  В него могут приходить ошибки и данные
      –  cтиль node.js
      –  callback(err, data)




13
Event: EventEmitter, PubSub
     Общая схема


      function EventEmitter () {
          this.events = {};
      }

      EventEmitter.prototype = {
          on: function (event, callback) {},
          off: function (event, callback) {},
          emit: function (event, data) {}
      };




14
                                   http://nodejs.org/api/events.html
Event
     Типичный пример – обертка над XMLHttpRequest


      function eventXHR(method, url, data) {
          var xhr = new XMLHttpRequest(),
              event = new EventEmitter();

           xhr.open(method, url, true);
           xhr.onreadystatechange = function () {
               if (xhr.readyState === 4) {
                   if (xhr.status === 200) {
                       event.emit(‘data’, xhr.responseText);
                   } else {
                       event.emit(‘error’);
                   }
               }
           }
           xhr.send(data);
           return event;
      }

15
Event
     Сам код. Изменилось не так много.

      eventXHR('GET', ‘http://host1/page.json’)
      .on(‘data’, function (data) {
          data = processData(data);
          var counter = 2;

           function done() {
               counter--;
               if (!counter) alert(‘Done!’);
           }

          eventXHR(‘POST’, ‘http://host2/result/’, data)
              .on(‘data’, done);
          eventXHR(‘POST’, ‘http://host3/result/’, data)
              .on(‘data’, done);
      })
      .on(‘error’, function(){ });



16
Event



     •  Абстракция более высокого уровня
     •  Ошибки отделены от данных
      –  Возможны логически разные типы данных

     •  Можно отписаться от события
     •  Можно подписаться несколько раз
     •  Можно передавать как аргумент


17
Promise


     •  Это Обещанные данные
     •  Имеет 3 состояния
      –  Не выполнен (выполняется)
      –  Выполнен (результат)
      –  Отклонен (ошибка)

     •  Меняет состояние только 1 раз
      –  В событиях состояние меняется сколько угодно раз

     •  Запоминает свое состояние
      –  В отличии от события в котором состояние – это поток



18
                  http://wiki.commonjs.org/wiki/Promises
Promise
     Общая схема


      function Promise () {
          this.isFulfilled = false;
          this.isRejected = false;
          this.isResolved = false;
          this.result = null;
      }

      Promise.prototype = {
          then: function (fulfilled, rejected, progressed) {},
          reject: function (error) {},
          resolve: function (data) {}
      };




19
Promise
     Типичный пример – обертка над XMLHttpRequest


      function promiseXHR(method, url, data) {
          var xhr = new XMLHttpRequest(),
              promise = new Promise();

           xhr.open(method, url, true);
           xhr.onreadystatechange = function () {
               if (xhr.readyState === 4) {
                   if (xhr.status === 200) {
                       promise.resolve(xhr.responseText);
                   } else {
                       promise.reject(‘Error ’ + xhr.status);
                   }
               }
           }
           xhr.send(data);
           return promise;
      }

20
Promise
     Сам код

      promiseXHR('GET', ‘http://host1/page.json’)
      .then(function (data) {
          data = processData(data);
          var promises = [
              promiseXHR(‘POST’, ‘http://host2/result/’, data),
              promiseXHR(‘POST’, ‘http://host3/result/’, data)
          ];

            when(promises, function (data) {
                alert(‘Done!’);
            });
      });




21
Promise



     •  Запоминает свое состояние
     •  Всегда возвращает один результат
      –  В отличие от события где данные – поток
      –  Не зависит от времени опроса

     •  Можно передавать как аргумент
     •  Можно выполнять операции
      –  then




22
Deferred




     •  Это защищенный Promise
     •  Разграничивает слушателя и Promise
     •  Слушатель не может вмешаться
      –  С чистыми промисами можно завершить промис на слушателе
      –  Меньше логических ошибок




23
        http://api.jquery.com/category/deferred-object/
Deferred
     Общая схема


      function Deferred () {
          this._promise = {
              then: function (fulfilled, rejected, progressed) {}
          };
      }

      Deferred.prototype = {
          promise: function (error) {
              return this._promise;
          },
          reject: function (error) {},
          resolve: function (data) {}
      };




24
Deferred
     Типичный пример – обертка над XMLHttpRequest


      function defferedXHR(method, url, data) {
          var xhr = new XMLHttpRequest(),
              deferred = new Deffered();

           xhr.open(method, url, true);
           xhr.onreadystatechange = function () {
               if (xhr.readyState === 4) {
                   if (xhr.status === 200) {
                       deferred.resolve(xhr.responseText);
                   } else {
                       deferred.reject(‘Error ’ + xhr.status);
                   }
               }
           }
           xhr.send(data);
           return deferred.promise();
      }

25
Deferred
     Сам код

      defferedXHR('GET', ‘http://host1/page.json’)
      .then(function (data) {
          data = processData(data);
          var promises = [
              defferedXHR(‘POST’, ‘http://host2/result/’, data),
              defferedXHR(‘POST’, ‘http://host3/result/’, data)
          ];

           when(promises, function (data) {
               alert(‘Done!’);
           });
      })
      .reject(‘Mua-ha-ha!’); // Это сделать нельзя




26
Библиотеки

Streamlinejs,
Fibers
Step,
Q
Streamline
     Streamline – попытка избавится от асинхронного шума
     Используют callback(err, data)




      var data = asyncXHR('GET', '/', null, _);
      asyncXHR('POST', '/', data, _);
      asyncXHR('POST', '/', data, _);
      alert('Done!');




28
                              https://github.com/Sage/streamlinejs
Streamline – результат генерации
     Happy Debug!

      (function main(_) {
        var data;
        var __frame = {
           name: "main”,
           line: 1
        };

        return __func(_, this, arguments, main, 0, __frame, function __$main() {
          return asyncXHR("GET", "/", null, __cb(_, __frame, 17, 11, function ___(__0, __1) {
            data = __1;
            return asyncXHR("POST", "/", data, __cb(_, __frame, 18, 0, function __$main() {
              return asyncXHR("POST", "/", data, __cb(_, __frame, 19, 0, function __$main() {
                alert("Done!");
                _();
              }, true));
            }, true));
          }, true));
        });
      }).call(this, __trap);




29
Streamlinejs



     •  Генерация кода – результат ужасен!
     •  Шум из массы _
     •  Его цель – выполнять асинхронный код
        последовательно




30
Fibers
     Fibers – попытка избавится от асинхронного шума
     Используют callback(err, data)

      var Future = require('fibers/future'),
          wait = Future.wait;

      var asyncXHR = Future.wrap(asyncXHR);

      Fiber(function () {
          var data = asyncXHR(‘GET’, '...’, null).wait();
          data = processData(data);

          asyncXHR(‘POST’, '...’, data).wait();
          asyncXHR(‘POST’, '...’, data).wait();
          alert(‘Done!’);
      }).run();



                          https://github.com/laverdet/node-fibers	

31                           https://github.com/0ctave/node-sync
Fibers


     •  Особая версия Node.js
      –  Хак механизма yield()

     •  Похожи на треды
      –  Не могут прерываться где угодно процессором
      –  Меньше расходов на «безопасные зоны»

     •  Похожи на Event Loop
      –  yield() и ручное прерывание фибера
      –  Блокировка остальных фиберов
      –  Нет реального параллелизма (не занимают все ядра процессора)

     •  Параллельные запросы последовательно
      –  Необходимо использовать дополнительные функции


32
Step
     Позволяет выполнять асинхронный код в синхронном стиле
     Работает с callback(err, data)

      Step(
          function () {
              asyncXHR('GET’, ‘...’, null, this);
          },
          function (err, data) {
              return processData(data);
          },
          function (err, data) {
              asyncXHR(‘POST’, ‘...’, data, this.parallel());
              asyncXHR(‘POST’, ‘...’, data, this.parallel());
          },
          function (err, result1, result2) {
              alert(‘Done!’);
          }
      );


33
                                https://github.com/creationix/step
Q
     Работает с Promise
     Представляет интерфейс для работы с промисами

      var data = promiseXHR('GET', '...');

      data.than(processAndSendData).than(function () {
          alert(‘Done!’);
      });

      function processAndSendData(data) {
          data = processData(data);
          return sendData(data);
      }

      function sendData(data) {
          return Q.all([
              promiseXHR(‘POST’, ‘...’, data),
              promiseXHR(‘POST’, ‘...’, data)
          ]);
      }

34
                                    https://github.com/kriskowal/q
Асинхронность

     •  Событийный ввод-вывод
     •  Работа с GUI
     •  Паттерны
      –  Callback
      –  EventEmitter
      –  Promise
      –  Deferred

     •  Хаки
      –  Streamline
      –  Fibers

     •  Библиотеки
      –  Step
      –  Q
35
Михаил Давыдов

     Разработчик JavaScript




     azproduction@yandex-team.ru
     azproduction




Спасибо

More Related Content

PDF
Михаил Давыдов — JavaScript: Асинхронность
PDF
Асинхронный JavaScript
PDF
Михаил Давыдов: JavaScript. Асинхронность
PPTX
Григорий Демченко, Универсальный адаптер
PPT
Javascript
PPT
Подробная презентация JavaScript 6 в 1
PDF
Живые приложения с Rx
PDF
RxJava+RxAndroid (Lecture 20 – rx java)
Михаил Давыдов — JavaScript: Асинхронность
Асинхронный JavaScript
Михаил Давыдов: JavaScript. Асинхронность
Григорий Демченко, Универсальный адаптер
Javascript
Подробная презентация JavaScript 6 в 1
Живые приложения с Rx
RxJava+RxAndroid (Lecture 20 – rx java)

What's hot (19)

PDF
Подводные камни System.Security.Cryptography
PDF
Школа-студия разработки для iOS. Лекция 4. Работа с данными
PPTX
Взломать сайт на ASP.NET
PPTX
Подводные камни прикладной криптографии, I
PPTX
Stream API: рекомендации лучших собаководов
PPTX
MongoDB - About Performance Optimization, Ivan Griga - Smart Gamma
PDF
Интуит. Разработка приложений для iOS. Лекция 8. Работа с данными
PPTX
Владимир Горбенко «Использование блоков в Objective-C»
PDF
Web осень 2013 лекция 2
PDF
Многопоточность, работа с сетью (Lecture 12 – multithreading, network)
PPT
Подробная презентация JavaScript 6 в 1
PDF
FrontTalks: Михаил Давыдов (Яндекс), «Promise – это не больно»
PPTX
Developing highload servers with Java
PDF
Библиотеки для передачи данных (Lecture 13 – multithreading, network (libs))
PPTX
Игорь Любин - Автотестирование веб-сервиса с Ruby и Rspec
PPTX
ObjectManager, или как работать с большим количеством объектов на карте, Мари...
PDF
Caching data outside Java Heap and using Shared Memory in Java
PDF
SECON'2014 - Павел Щеваев - Метаданные и автогенерация кода
PDF
What's in a metrics? Ruby Russia 2018
Подводные камни System.Security.Cryptography
Школа-студия разработки для iOS. Лекция 4. Работа с данными
Взломать сайт на ASP.NET
Подводные камни прикладной криптографии, I
Stream API: рекомендации лучших собаководов
MongoDB - About Performance Optimization, Ivan Griga - Smart Gamma
Интуит. Разработка приложений для iOS. Лекция 8. Работа с данными
Владимир Горбенко «Использование блоков в Objective-C»
Web осень 2013 лекция 2
Многопоточность, работа с сетью (Lecture 12 – multithreading, network)
Подробная презентация JavaScript 6 в 1
FrontTalks: Михаил Давыдов (Яндекс), «Promise – это не больно»
Developing highload servers with Java
Библиотеки для передачи данных (Lecture 13 – multithreading, network (libs))
Игорь Любин - Автотестирование веб-сервиса с Ruby и Rspec
ObjectManager, или как работать с большим количеством объектов на карте, Мари...
Caching data outside Java Heap and using Shared Memory in Java
SECON'2014 - Павел Щеваев - Метаданные и автогенерация кода
What's in a metrics? Ruby Russia 2018
Ad

Viewers also liked (9)

PDF
Дмитрий Вульбрун — Новая выдача Поиска для сайта
PDF
Михаил Корепанов "Инкрементальные обновления на клиенте. Ловкость рук и никак...
PDF
"How the Universe is put to the test" – Andrei Golutvin, Ulrik Egede, CERN
PDF
Игорь Шевченко — Новая выдача Поиска для сайта - кастомные теги, CSS3 и JavaS...
PDF
Вячеслав Олиянчук — Яндекс.Авто 2.0 на Node.js
DOCX
Angie carolina barrera monzo
PDF
Кирилл Меркушев — Матчеры: польза использования и легкость применения в ваших...
PDF
"Быстрое обнаружение вредоносного ПО для Android с помощью машинного обучения...
PDF
"Securing eCommerce with Data Metrics". Corey Benninger, Etsy
Дмитрий Вульбрун — Новая выдача Поиска для сайта
Михаил Корепанов "Инкрементальные обновления на клиенте. Ловкость рук и никак...
"How the Universe is put to the test" – Andrei Golutvin, Ulrik Egede, CERN
Игорь Шевченко — Новая выдача Поиска для сайта - кастомные теги, CSS3 и JavaS...
Вячеслав Олиянчук — Яндекс.Авто 2.0 на Node.js
Angie carolina barrera monzo
Кирилл Меркушев — Матчеры: польза использования и легкость применения в ваших...
"Быстрое обнаружение вредоносного ПО для Android с помощью машинного обучения...
"Securing eCommerce with Data Metrics". Corey Benninger, Etsy
Ad

Similar to Михаил Давыдов - JavaScript. Асинхронность (20)

PDF
JavaScript. Async (in Russian)
PDF
Михаил Давыдов — Транспорт, Ajax
PDF
Mihail davidov js-ajax
PPT
Web весна 2013 лекция 9
PDF
DevConf. Дмитрий Сошников - ECMAScript 6
PDF
Кэширование данных с помощью Service Worker
PPT
Mike ponomarenko java17-fork-v1.2
PDF
Стажировка 2016-07-14 02 Евгений Тарасенко. JavaScript
PDF
Курсы актерского мастерства
PPTX
I tmozg js_school_jquery
PPTX
Solit 2014, Реактивный Javascript. Победа над асинхронностью и вложенностью, ...
PDF
2014-10-04 02 Владислав Безверхий. Mocha - покрой frontend по полной
PPTX
course js day 2
PPT
Web весна 2012 лекция 9
PDF
Киллер-фича языка C# — конструкция async/await
PPTX
Примеры быстрой разработки API на масштабируемом сервере приложений Impress д...
PDF
16 - Web-технологии. Технология AJAX
PPTX
разработка серверов и серверных приложений лекция №3
PPTX
разработка серверов и серверных приложений лекция №3
PDF
Организация работы с API на Vue.js, Виталий Копачёв
JavaScript. Async (in Russian)
Михаил Давыдов — Транспорт, Ajax
Mihail davidov js-ajax
Web весна 2013 лекция 9
DevConf. Дмитрий Сошников - ECMAScript 6
Кэширование данных с помощью Service Worker
Mike ponomarenko java17-fork-v1.2
Стажировка 2016-07-14 02 Евгений Тарасенко. JavaScript
Курсы актерского мастерства
I tmozg js_school_jquery
Solit 2014, Реактивный Javascript. Победа над асинхронностью и вложенностью, ...
2014-10-04 02 Владислав Безверхий. Mocha - покрой frontend по полной
course js day 2
Web весна 2012 лекция 9
Киллер-фича языка C# — конструкция async/await
Примеры быстрой разработки API на масштабируемом сервере приложений Impress д...
16 - Web-технологии. Технология AJAX
разработка серверов и серверных приложений лекция №3
разработка серверов и серверных приложений лекция №3
Организация работы с API на Vue.js, Виталий Копачёв

More from Yandex (20)

PDF
Предсказание оттока игроков из World of Tanks
PDF
Как принять/организовать работу по поисковой оптимизации сайта, Сергей Царик,...
PDF
Структурированные данные, Юлия Тихоход, лекция в Школе вебмастеров Яндекса
PDF
Представление сайта в поиске, Сергей Лысенко, лекция в Школе вебмастеров Яндекса
PDF
Плохие методы продвижения сайта, Екатерины Гладких, лекция в Школе вебмастеро...
PDF
Основные принципы ранжирования, Сергей Царик и Антон Роменский, лекция в Школ...
PDF
Основные принципы индексирования сайта, Александр Смирнов, лекция в Школе веб...
PDF
Мобильное приложение: как и зачем, Александр Лукин, лекция в Школе вебмастеро...
PDF
Сайты на мобильных устройствах, Олег Ножичкин, лекция в Школе вебмастеров Янд...
PDF
Качественная аналитика сайта, Юрий Батиевский, лекция в Школе вебмастеров Янд...
PDF
Что можно и что нужно измерять на сайте, Петр Аброськин, лекция в Школе вебма...
PDF
Как правильно поставить ТЗ на создание сайта, Алексей Бородкин, лекция в Школ...
PDF
Как защитить свой сайт, Пётр Волков, лекция в Школе вебмастеров
PDF
Как правильно составить структуру сайта, Дмитрий Сатин, лекция в Школе вебмас...
PDF
Технические особенности создания сайта, Дмитрий Васильева, лекция в Школе веб...
PDF
Конструкторы для отдельных элементов сайта, Елена Першина, лекция в Школе веб...
PDF
Контент для интернет-магазинов, Катерина Ерошина, лекция в Школе вебмастеров ...
PDF
Как написать хороший текст для сайта, Катерина Ерошина, лекция в Школе вебмас...
PDF
Usability и дизайн - как не помешать пользователю, Алексей Иванов, лекция в Ш...
PDF
Cайт. Зачем он и каким должен быть, Алексей Иванов, лекция в Школе вебмастеро...
Предсказание оттока игроков из World of Tanks
Как принять/организовать работу по поисковой оптимизации сайта, Сергей Царик,...
Структурированные данные, Юлия Тихоход, лекция в Школе вебмастеров Яндекса
Представление сайта в поиске, Сергей Лысенко, лекция в Школе вебмастеров Яндекса
Плохие методы продвижения сайта, Екатерины Гладких, лекция в Школе вебмастеро...
Основные принципы ранжирования, Сергей Царик и Антон Роменский, лекция в Школ...
Основные принципы индексирования сайта, Александр Смирнов, лекция в Школе веб...
Мобильное приложение: как и зачем, Александр Лукин, лекция в Школе вебмастеро...
Сайты на мобильных устройствах, Олег Ножичкин, лекция в Школе вебмастеров Янд...
Качественная аналитика сайта, Юрий Батиевский, лекция в Школе вебмастеров Янд...
Что можно и что нужно измерять на сайте, Петр Аброськин, лекция в Школе вебма...
Как правильно поставить ТЗ на создание сайта, Алексей Бородкин, лекция в Школ...
Как защитить свой сайт, Пётр Волков, лекция в Школе вебмастеров
Как правильно составить структуру сайта, Дмитрий Сатин, лекция в Школе вебмас...
Технические особенности создания сайта, Дмитрий Васильева, лекция в Школе веб...
Конструкторы для отдельных элементов сайта, Елена Першина, лекция в Школе веб...
Контент для интернет-магазинов, Катерина Ерошина, лекция в Школе вебмастеров ...
Как написать хороший текст для сайта, Катерина Ерошина, лекция в Школе вебмас...
Usability и дизайн - как не помешать пользователю, Алексей Иванов, лекция в Ш...
Cайт. Зачем он и каким должен быть, Алексей Иванов, лекция в Школе вебмастеро...

Михаил Давыдов - JavaScript. Асинхронность

  • 3. Задача •  Качаем 1 файл •  После отправляем данные на 2 сервера •  Синхронизируемся 3
  • 4. Синхронный код Сделаем обертку над XMLHttpRequest function syncXHR(method, url, data) { var xhr = new XMLHttpRequest(); xhr.open(method, url, false); xhr.send(data); return xhr.responseText; } var data = syncXHR('GET', 'http://host1/page.json'); data = processData(data); syncXHR('POST', 'http://host2/result/', data); syncXHR('POST', 'http://host3/result/', data); alert('Done!'); 4
  • 5. Схема загрузки Подготовка Обработка Отправка Алерт Блокировка Блокировка Блокировка Запрос Запрос Запрос 5 время
  • 6. Асинхронный код Сделаем обертку над XMLHttpRequest function asyncXHR(method, url, data, callback) { var xhr = new XMLHttpRequest(); xhr.open(method, url, true); xhr.onreadystatechange = function () { if (xhr.readyState === 4) { if (xhr.status === 200) { callback(null, xhr.responseText); } else { callback(‘error’); } } } xhr.send(data); } 6
  • 7. Асинхронный код Сам код. Изменилось все. asyncXHR ('GET', ‘http://host1/page.json’, null, function (err, data) { data = processData(data); var counter = 2; function done(err, data) { counter--; if (!counter) alert(‘Done!’); } asyncXHR(‘POST’, ‘http://host2/result/’, data, done); asyncXHR(‘POST’, ‘http://host3/result/’, data, done); }); 7
  • 8. Схема загрузки Подготовка Обработка Отправка Алерт Ожидание Ожидание Запрос 8 время
  • 9. Где применяется "асинхронность" •  Производительность •  Интерфейс пользователя •  Проблемы –  Много лишнего шума –  Проблема синхронизации –  Куча вложенных колбэков: Pyramid of Doom •  Несколько реализаций –  Event Loop 9
  • 10. Основа – Event Loop •  Основа всех событийных систем •  Использует очередь событий •  Ждет события •  Выполняет события из очереди –  События в очередь поступают во время выполнения событий –  События генерируют события •  Завершается когда очередь пуста 10
  • 12. Callback Типичный пример – обертка над XMLHttpRequest function asyncXHR(method, url, data, callback) { var xhr = new XMLHttpRequest(); xhr.open(method, url, true); xhr.onreadystatechange = function () { if (xhr.readyState === 4) { if (xhr.status === 200) { callback(null, xhr.responseText); } else { callback(‘error’); } } } xhr.send(data); } 12
  • 13. Callback •  Самый простой вариант –  Дешевая абстракция •  В него могут приходить ошибки и данные –  cтиль node.js –  callback(err, data) 13
  • 14. Event: EventEmitter, PubSub Общая схема function EventEmitter () { this.events = {}; } EventEmitter.prototype = { on: function (event, callback) {}, off: function (event, callback) {}, emit: function (event, data) {} }; 14 http://nodejs.org/api/events.html
  • 15. Event Типичный пример – обертка над XMLHttpRequest function eventXHR(method, url, data) { var xhr = new XMLHttpRequest(), event = new EventEmitter(); xhr.open(method, url, true); xhr.onreadystatechange = function () { if (xhr.readyState === 4) { if (xhr.status === 200) { event.emit(‘data’, xhr.responseText); } else { event.emit(‘error’); } } } xhr.send(data); return event; } 15
  • 16. Event Сам код. Изменилось не так много. eventXHR('GET', ‘http://host1/page.json’) .on(‘data’, function (data) { data = processData(data); var counter = 2; function done() { counter--; if (!counter) alert(‘Done!’); } eventXHR(‘POST’, ‘http://host2/result/’, data) .on(‘data’, done); eventXHR(‘POST’, ‘http://host3/result/’, data) .on(‘data’, done); }) .on(‘error’, function(){ }); 16
  • 17. Event •  Абстракция более высокого уровня •  Ошибки отделены от данных –  Возможны логически разные типы данных •  Можно отписаться от события •  Можно подписаться несколько раз •  Можно передавать как аргумент 17
  • 18. Promise •  Это Обещанные данные •  Имеет 3 состояния –  Не выполнен (выполняется) –  Выполнен (результат) –  Отклонен (ошибка) •  Меняет состояние только 1 раз –  В событиях состояние меняется сколько угодно раз •  Запоминает свое состояние –  В отличии от события в котором состояние – это поток 18 http://wiki.commonjs.org/wiki/Promises
  • 19. Promise Общая схема function Promise () { this.isFulfilled = false; this.isRejected = false; this.isResolved = false; this.result = null; } Promise.prototype = { then: function (fulfilled, rejected, progressed) {}, reject: function (error) {}, resolve: function (data) {} }; 19
  • 20. Promise Типичный пример – обертка над XMLHttpRequest function promiseXHR(method, url, data) { var xhr = new XMLHttpRequest(), promise = new Promise(); xhr.open(method, url, true); xhr.onreadystatechange = function () { if (xhr.readyState === 4) { if (xhr.status === 200) { promise.resolve(xhr.responseText); } else { promise.reject(‘Error ’ + xhr.status); } } } xhr.send(data); return promise; } 20
  • 21. Promise Сам код promiseXHR('GET', ‘http://host1/page.json’) .then(function (data) { data = processData(data); var promises = [ promiseXHR(‘POST’, ‘http://host2/result/’, data), promiseXHR(‘POST’, ‘http://host3/result/’, data) ]; when(promises, function (data) { alert(‘Done!’); }); }); 21
  • 22. Promise •  Запоминает свое состояние •  Всегда возвращает один результат –  В отличие от события где данные – поток –  Не зависит от времени опроса •  Можно передавать как аргумент •  Можно выполнять операции –  then 22
  • 23. Deferred •  Это защищенный Promise •  Разграничивает слушателя и Promise •  Слушатель не может вмешаться –  С чистыми промисами можно завершить промис на слушателе –  Меньше логических ошибок 23 http://api.jquery.com/category/deferred-object/
  • 24. Deferred Общая схема function Deferred () { this._promise = { then: function (fulfilled, rejected, progressed) {} }; } Deferred.prototype = { promise: function (error) { return this._promise; }, reject: function (error) {}, resolve: function (data) {} }; 24
  • 25. Deferred Типичный пример – обертка над XMLHttpRequest function defferedXHR(method, url, data) { var xhr = new XMLHttpRequest(), deferred = new Deffered(); xhr.open(method, url, true); xhr.onreadystatechange = function () { if (xhr.readyState === 4) { if (xhr.status === 200) { deferred.resolve(xhr.responseText); } else { deferred.reject(‘Error ’ + xhr.status); } } } xhr.send(data); return deferred.promise(); } 25
  • 26. Deferred Сам код defferedXHR('GET', ‘http://host1/page.json’) .then(function (data) { data = processData(data); var promises = [ defferedXHR(‘POST’, ‘http://host2/result/’, data), defferedXHR(‘POST’, ‘http://host3/result/’, data) ]; when(promises, function (data) { alert(‘Done!’); }); }) .reject(‘Mua-ha-ha!’); // Это сделать нельзя 26
  • 28. Streamline Streamline – попытка избавится от асинхронного шума Используют callback(err, data) var data = asyncXHR('GET', '/', null, _); asyncXHR('POST', '/', data, _); asyncXHR('POST', '/', data, _); alert('Done!'); 28 https://github.com/Sage/streamlinejs
  • 29. Streamline – результат генерации Happy Debug! (function main(_) { var data; var __frame = { name: "main”, line: 1 }; return __func(_, this, arguments, main, 0, __frame, function __$main() { return asyncXHR("GET", "/", null, __cb(_, __frame, 17, 11, function ___(__0, __1) { data = __1; return asyncXHR("POST", "/", data, __cb(_, __frame, 18, 0, function __$main() { return asyncXHR("POST", "/", data, __cb(_, __frame, 19, 0, function __$main() { alert("Done!"); _(); }, true)); }, true)); }, true)); }); }).call(this, __trap); 29
  • 30. Streamlinejs •  Генерация кода – результат ужасен! •  Шум из массы _ •  Его цель – выполнять асинхронный код последовательно 30
  • 31. Fibers Fibers – попытка избавится от асинхронного шума Используют callback(err, data) var Future = require('fibers/future'), wait = Future.wait; var asyncXHR = Future.wrap(asyncXHR); Fiber(function () { var data = asyncXHR(‘GET’, '...’, null).wait(); data = processData(data); asyncXHR(‘POST’, '...’, data).wait(); asyncXHR(‘POST’, '...’, data).wait(); alert(‘Done!’); }).run(); https://github.com/laverdet/node-fibers 31 https://github.com/0ctave/node-sync
  • 32. Fibers •  Особая версия Node.js –  Хак механизма yield() •  Похожи на треды –  Не могут прерываться где угодно процессором –  Меньше расходов на «безопасные зоны» •  Похожи на Event Loop –  yield() и ручное прерывание фибера –  Блокировка остальных фиберов –  Нет реального параллелизма (не занимают все ядра процессора) •  Параллельные запросы последовательно –  Необходимо использовать дополнительные функции 32
  • 33. Step Позволяет выполнять асинхронный код в синхронном стиле Работает с callback(err, data) Step( function () { asyncXHR('GET’, ‘...’, null, this); }, function (err, data) { return processData(data); }, function (err, data) { asyncXHR(‘POST’, ‘...’, data, this.parallel()); asyncXHR(‘POST’, ‘...’, data, this.parallel()); }, function (err, result1, result2) { alert(‘Done!’); } ); 33 https://github.com/creationix/step
  • 34. Q Работает с Promise Представляет интерфейс для работы с промисами var data = promiseXHR('GET', '...'); data.than(processAndSendData).than(function () { alert(‘Done!’); }); function processAndSendData(data) { data = processData(data); return sendData(data); } function sendData(data) { return Q.all([ promiseXHR(‘POST’, ‘...’, data), promiseXHR(‘POST’, ‘...’, data) ]); } 34 https://github.com/kriskowal/q
  • 35. Асинхронность •  Событийный ввод-вывод •  Работа с GUI •  Паттерны –  Callback –  EventEmitter –  Promise –  Deferred •  Хаки –  Streamline –  Fibers •  Библиотеки –  Step –  Q 35
  • 36. Михаил Давыдов Разработчик JavaScript azproduction@yandex-team.ru azproduction Спасибо