0
JavaScriptАсинхронностьМихаил ДавыдовРазработчик JavaScript
Задача    •  Качаем 1 файл    •  После отправляем данные на 2 сервера    •  Синхронизируемся3
Синхронный код    Сделаем обертку над XMLHttpRequest     function syncXHR(method, url, data) {         var xhr = new XMLHt...
Схема загрузки    Подготовка            Обработка                Отправка                Алерт             Блокировка     ...
Асинхронный код    Сделаем обертку над XMLHttpRequest     function asyncXHR(method, url, data, callback) {         var xhr...
Асинхронный код    Сам код. Изменилось все.     asyncXHR (GET, ‘http://host1/page.json’, null,     function (err, data) { ...
Схема загрузки      Подготовка             Обработка Отправка              Алерт                   Ожидание               ...
Асинхронность    •  Производительность     –  Код выше    •  Интерфейс пользователя    •  Проблемы     –  Много лишнего шу...
Event Loop     •  Основа всех событийных систем     •  Использует очередь событий     •  Ждет события     •  Выполняет соб...
ПаттерныCallback,Event,Promise,Deferred
Callback     Типичный пример – обертка над XMLHttpRequest      function asyncXHR(method, url, data, callback) {          v...
Callback     •  Самый простой вариант      –  Дешевая абстракция     •  В него могут приходить ошибки и данные      –  cти...
Event: EventEmitter, PubSub     Общая схема      function EventEmitter () {          this.events = {};      }      EventEm...
Event     Типичный пример – обертка над XMLHttpRequest      function eventXHR(method, url, data) {          var xhr = new ...
Event     Сам код. Изменилось не так много.      eventXHR(GET, ‘http://host1/page.json’)      .on(‘data’, function (data) ...
Event     •  Абстракция более высокого уровня     •  Ошибки отделены от данных      –  Возможны логически разные типы данн...
Promise     •  Это Обещанные данные     •  Имеет 3 состояния      –  Не выполнен (выполняется)      –  Выполнен (результат...
Promise     Общая схема      function Promise () {          this.isFulfilled = false;          this.isRejected = false;   ...
Promise     Типичный пример – обертка над XMLHttpRequest      function promiseXHR(method, url, data) {          var xhr = ...
Promise     Сам код      promiseXHR(GET, ‘http://host1/page.json’)      .then(function (data) {          data = processDat...
Promise     •  Запоминает свое состояние     •  Всегда возвращает один результат      –  В отличие от события где данные –...
Deferred     •  Это защищенный Promise     •  Разграничивает слушателя и Promise     •  Слушатель не может вмешаться      ...
Deferred     Общая схема      function Deferred () {          this._promise = {              then: function (fulfilled, re...
Deferred     Типичный пример – обертка над XMLHttpRequest      function defferedXHR(method, url, data) {          var xhr ...
Deferred     Сам код      defferedXHR(GET, ‘http://host1/page.json’)      .then(function (data) {          data = processD...
БиблиотекиStreamlinejs,FibersStep,Q
Streamline     Streamline – попытка избавится от асинхронного шума     Используют callback(err, data)      var data = asyn...
Streamline – результат генерации     Happy Debug!      (function main(_) {        var data;        var __frame = {        ...
Streamlinejs     •  Генерация кода – результат ужасен!     •  Шум из массы _     •  Его цель – выполнять асинхронный код  ...
Fibers     Fibers – попытка избавится от асинхронного шума     Используют callback(err, data)      var Future = require(fi...
Fibers     •  Особая версия Node.js      –  Хак механизма yield()     •  Похожи на треды      –  Не могут прерываться где ...
Step     Позволяет выполнять асинхронный код в синхронном стиле     Работает с callback(err, data)      Step(          fun...
Q     Работает с Promise     Представляет интерфейс для работы с промисами      var data = promiseXHR(GET, ...);      data...
Асинхронность     •  Событийный ввод-вывод     •  Работа с GUI     •  Паттерны      –  Callback      –  EventEmitter      ...
Михаил Давыдов     Разработчик JavaScript     azproduction@yandex-team.ru     azproductionСпасибо
Михаил Давыдов — JavaScript: Асинхронность
Upcoming SlideShare
Loading in...5
×

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

5,506

Published on

Published in: Technology
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
5,506
On Slideshare
0
From Embeds
0
Number of Embeds
5
Actions
Shares
0
Downloads
8
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

Transcript of "Михаил Давыдов — JavaScript: Асинхронность"

  1. 1. JavaScriptАсинхронностьМихаил ДавыдовРазработчик JavaScript
  2. 2. Задача •  Качаем 1 файл •  После отправляем данные на 2 сервера •  Синхронизируемся3
  3. 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
  4. 4. Схема загрузки Подготовка Обработка Отправка Алерт Блокировка Блокировка Блокировка Запрос Запрос Запрос5 время
  5. 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
  6. 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
  7. 7. Схема загрузки Подготовка Обработка Отправка Алерт Ожидание Ожидание Запрос8 время
  8. 8. Асинхронность •  Производительность –  Код выше •  Интерфейс пользователя •  Проблемы –  Много лишнего шума –  Проблема синхронизации –  Куча вложенных колбэков: Pyramid of Doom •  Несколько реализаций –  Event Loop9
  9. 9. Event Loop •  Основа всех событийных систем •  Использует очередь событий •  Ждет события •  Выполняет события из очереди –  События в очередь поступают во время выполнения событий –  События генерируют события •  Завершается когда очередь пуста10
  10. 10. ПаттерныCallback,Event,Promise,Deferred
  11. 11. 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
  12. 12. Callback •  Самый простой вариант –  Дешевая абстракция •  В него могут приходить ошибки и данные –  cтиль node.js –  callback(err, data)13
  13. 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
  14. 14. 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
  15. 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
  16. 16. Event •  Абстракция более высокого уровня •  Ошибки отделены от данных –  Возможны логически разные типы данных •  Можно отписаться от события •  Можно подписаться несколько раз •  Можно передавать как аргумент17
  17. 17. Promise •  Это Обещанные данные •  Имеет 3 состояния –  Не выполнен (выполняется) –  Выполнен (результат) –  Отклонен (ошибка) •  Меняет состояние только 1 раз –  В событиях состояние меняется сколько угодно раз •  Запоминает свое состояние –  В отличии от события в котором состояние – это поток18 http://wiki.commonjs.org/wiki/Promises
  18. 18. 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
  19. 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
  20. 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
  21. 21. Promise •  Запоминает свое состояние •  Всегда возвращает один результат –  В отличие от события где данные – поток –  Не зависит от времени опроса •  Можно передавать как аргумент •  Можно выполнять операции –  then22
  22. 22. Deferred •  Это защищенный Promise •  Разграничивает слушателя и Promise •  Слушатель не может вмешаться –  С чистыми промисами можно завершить промис на слушателе –  Меньше логических ошибок23 http://api.jquery.com/category/deferred-object/
  23. 23. 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
  24. 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
  25. 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
  26. 26. БиблиотекиStreamlinejs,FibersStep,Q
  27. 27. Streamline Streamline – попытка избавится от асинхронного шума Используют callback(err, data) var data = asyncXHR(GET, /, null, _); asyncXHR(POST, /, data, _); asyncXHR(POST, /, data, _); alert(Done!);28 https://github.com/Sage/streamlinejs
  28. 28. 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
  29. 29. Streamlinejs •  Генерация кода – результат ужасен! •  Шум из массы _ •  Его цель – выполнять асинхронный код последовательно30
  30. 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
  31. 31. Fibers •  Особая версия Node.js –  Хак механизма yield() •  Похожи на треды –  Не могут прерываться где угодно процессором –  Меньше расходов на «безопасные зоны» •  Похожи на Event Loop –  yield() и ручное прерывание фибера –  Блокировка остальных фиберов –  Нет реального параллелизма (не занимают все ядра процессора) •  Параллельные запросы последовательно –  Необходимо использовать дополнительные функции32
  32. 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
  33. 33. 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
  34. 34. Асинхронность •  Событийный ввод-вывод •  Работа с GUI •  Паттерны –  Callback –  EventEmitter –  Promise –  Deferred •  Хаки –  Streamline –  Fibers •  Библиотеки –  Step –  Q35
  35. 35. Михаил Давыдов Разработчик JavaScript azproduction@yandex-team.ru azproductionСпасибо
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×