Promise —
это не
больно!
Михаил Давыдов, JavaScript-разработчик
2013 год, FrontTalks
Асинхронность везде!
Запросы к серверу
04
Данные пользователя
05
События интерфейса
GARMOSHKA
06
∞
Таймеры и анимация
07
Когда один callback —
всё здорово!
Последовательные запросы
login('user:pass@server', function (err, server) {
if (err) return cb(err);
server.open('db', fun...
Параллельные запросы
var rows = [], total = view.length;
function fetch(err, row) {
if (err) return cb(err);
if (rows.leng...
Шум
login('user:pass@server', function (err, server) {
if (err) return cb(err);
server.open('db', function (err, db) {
if ...
Шум
● Статус ошибки
● Однообразная обработка ошибки
● Глубина вложенности
13
Сложно отменить действие
db.query(query, function (err, view) {});
Как отменить или игнорировать запрос в этом случае?
db....
Несколько обработчиков
query(query1, function (err, view) {});
query(query2, function (err, view) {});
query(query3, funct...
Делегирование результата
function uberQueryGenerator(data) {
// Готовим queryFromData
return query(queryFromData);
}
funct...
У callback-ов нет
единого интерфейса
Нет единого интерфейса
● Последний аргумент
● Свойство конфига или метод
– success
– complete
– done
– finish
– ???
18
Нет единого интерфейса
$('div').animate({}, function () {});
// А можно еще вот так
$('div').animate({}, {
complete: funct...
Нет единого интерфейса
$.ajax({
url: url
success: function () {}
});
$.ajax({
url: url
}).done(function () {});
01.
02.
03...
Магия
Магия
● Step.js
● Streamline.js
● Fibers
● ???
22
Step.js
Step(function login() {
login('user:pass@server', this);
}, function openDatabase(err, db) {
if (err) throw err;
d...
Streamline.js
var db = login('user:pass@server', _);
db.query(query, _);
Вроде бы ничего!
01.
02.
24
Streamline.js
(fstreamline__.create(function(_) {
var db = (yield fstreamline__
.invoke(null, login, ['user:pass@server', ...
Promise
● aka Futures
● Распостранен в других языках
● Стандартизирован Promise/A+
● Стандарт «Покрыт тестами» Promises/A+...
Promise
login('user:pass@server')
.then(function (server) {
return server.open('db');
})
.then(function (db) {
return db.q...
Promise
.then(function (view) {
return fetchRows(view);
}, function handleError(err) {
console.error(err);
}) // ...
Меньш...
Абстракция над обещанными
данными
● Обещание можно сдержать, а можно не выполнять
● Состояние изменяется только 1 раз
● Ре...
Реализация Promise
var Promise = function () {
this._value = null;
this.isFulfilled = false; // ok
this.isRejected = false...
Реализация Promise
Promise.prototype = {
// @return {Promise}
then: function (onFulfilled, onRejected) {},
fulfill: functi...
Использование Promise
// @param {Number} time
// @return {Promise}
function timeout(time) {
var promise = new Promise();
s...
Пример timeout
timeout(1000)
.then(function () {
console.log('first');
return timeout(1000);
})
.then(console.log.bind(con...
Пример timeout
timeout(1000)
.then(randomLog)
.then(console.log.bind(console, 'done!'));
function randomLog() {
var rnd = ...
Promise
● Не хак и не магия
● Единый интерфейс всех промисов
● Меньше шума в коде
● Разделение логики на шаги
● ...
● PROF...
Трюки с Promise
Склеивание Promise
// $.when - агрегатор Promise
// Результат не раньше, чем через 1с
$.when($.get('/'), $.get('/?'), time...
Повтор Promise
new Attempt(get404, repeat3Times)
.then(ok, epicFail, progress);
function get404() {
return $.get('/404');
...
Прозрачный кэш с Promise
var cache;
function request() {
return cache ? cache : cache = $.get('/');
}
request().then(funct...
Promise уже рядом!
● Браузер
– $.Deferred
– $.when, $.ajax, $.get, $.post, ...
● Node.js
– Q: q-io
– Vow: vow-fs, vow-aske...
Generators
● Решение проблем асинхронности будущего
● Оператор yield «Ставит выполнение кода на паузу»
● Когда?
– Node.js ...
Generators
var co = require('co');
co(function *() {
var server = yield login('user:pass@server'),
db = yield server.open(...
yield vs then?
Generators и Promise
● Именно «и», а не «VS»
● Используем вместе
– Библиотека Q
– Библиотека co
● С Generators код еще чищ...
Используйте Promise!
● Готов к использованию сегодня!
● Единый интерфейс
● Стандарт Promise/A+
● Структурирует код
● Меньш...
Promise — это не больно!
Михаил Давыдов
JavaScript-разработчик
@azproduction
50
Почитать
● Примеры с презентации
● Promises/A+
● Differences from Promises/A
● Design of Q library (настоятельно рекоменду...
clck.ru/8i9pr
FrontTalks: Михаил Давыдов (Яндекс), «Promise – это не больно»
FrontTalks: Михаил Давыдов (Яндекс), «Promise – это не больно»
FrontTalks: Михаил Давыдов (Яндекс), «Promise – это не больно»
FrontTalks: Михаил Давыдов (Яндекс), «Promise – это не больно»
FrontTalks: Михаил Давыдов (Яндекс), «Promise – это не больно»
FrontTalks: Михаил Давыдов (Яндекс), «Promise – это не больно»
Upcoming SlideShare
Loading in …5
×

FrontTalks: Михаил Давыдов (Яндекс), «Promise – это не больно»

1,576 views
1,447 views

Published on

Асинхронность в JavaScript-приложениях – обычное дело. Любой обмен данными – асинхронный, что HTTP, что чтение файла, что БД. Все просто, если запрос один – callback, и все дела. Если логика сложнее, то приложение в худшем случае превращается в «Callback Pyramid of Doom» или обрастает разной магией. Promise – это подход, который выпрямляет вложенные запросы, превращает «асинхронную лапшу» в структурированный код и делает ваше приложение лучше. Вы всё еще боитесь использовать Promise? Тогда приходите на мой доклад.

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

  • Be the first to like this

No Downloads
Views
Total views
1,576
On SlideShare
0
From Embeds
0
Number of Embeds
971
Actions
Shares
0
Downloads
5
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

FrontTalks: Михаил Давыдов (Яндекс), «Promise – это не больно»

  1. 1. Promise — это не больно! Михаил Давыдов, JavaScript-разработчик 2013 год, FrontTalks
  2. 2. Асинхронность везде!
  3. 3. Запросы к серверу 04
  4. 4. Данные пользователя 05
  5. 5. События интерфейса GARMOSHKA 06 ∞
  6. 6. Таймеры и анимация 07
  7. 7. Когда один callback — всё здорово!
  8. 8. Последовательные запросы login('user:pass@server', function (err, server) { if (err) return cb(err); server.open('db', function (err, db) { if (err) return cb(err); db.query(query, function (err, view) {}); }); }); 01. 02. 03. 04. 05. 06. 07. 10
  9. 9. Параллельные запросы var rows = [], total = view.length; function fetch(err, row) { if (err) return cb(err); if (rows.length === total) cb(null, rows); } for (var i = 0; i < total; i++) { view.get(i, fetch); } 01. 02. 03. 04. 05. 06. 07. 08. 11
  10. 10. Шум login('user:pass@server', function (err, server) { if (err) return cb(err); server.open('db', function (err, db) { if (err) return cb(err); db.query(query, function (err, view) {}); }); }); 01. 02. 03. 04. 05. 06. 07. 12
  11. 11. Шум ● Статус ошибки ● Однообразная обработка ошибки ● Глубина вложенности 13
  12. 12. Сложно отменить действие db.query(query, function (err, view) {}); Как отменить или игнорировать запрос в этом случае? db.query(query, fn).abort(); // .cancel() ? db.query(query, function (err) { if (err.message === 'abort') return; }); 01. 01. 02. 03. 04. 14
  13. 13. Несколько обработчиков query(query1, function (err, view) {}); query(query2, function (err, view) {}); query(query3, function (err, view) {}); 3 запроса — 3 попытки логина. Для кэша нужно еще дописать код. 01. 02. 03. 15
  14. 14. Делегирование результата function uberQueryGenerator(data) { // Готовим queryFromData return query(queryFromData); } function uberQueryGenerator(data, fn) { query(queryFromData, fn); } 01. 02. 03. 04. 01. 02. 03. 16
  15. 15. У callback-ов нет единого интерфейса
  16. 16. Нет единого интерфейса ● Последний аргумент ● Свойство конфига или метод – success – complete – done – finish – ??? 18
  17. 17. Нет единого интерфейса $('div').animate({}, function () {}); // А можно еще вот так $('div').animate({}, { complete: function () {} }); 01. 02. 03. 04. 05. 19
  18. 18. Нет единого интерфейса $.ajax({ url: url success: function () {} }); $.ajax({ url: url }).done(function () {}); 01. 02. 03. 04. 05. 06. 07. 20
  19. 19. Магия
  20. 20. Магия ● Step.js ● Streamline.js ● Fibers ● ??? 22
  21. 21. Step.js Step(function login() { login('user:pass@server', this); }, function openDatabase(err, db) { if (err) throw err; db.query(query, this); }); 01. 02. 03. 04. 05. 06. 23
  22. 22. Streamline.js var db = login('user:pass@server', _); db.query(query, _); Вроде бы ничего! 01. 02. 24
  23. 23. Streamline.js (fstreamline__.create(function(_) { var db = (yield fstreamline__ .invoke(null, login, ['user:pass@server', _], 1)); (yield fstreamline__.invoke(db, "query", [query, _], 1)); ;yield;}, 0).call(this, function(err) { if (err) throw err; })); 01. 02. 03. 04. 05. 06. 07. 25
  24. 24. Promise ● aka Futures ● Распостранен в других языках ● Стандартизирован Promise/A+ ● Стандарт «Покрыт тестами» Promises/A+ Compliance Test Suite ● Готовые абстракции над fs, http, ... 27
  25. 25. Promise login('user:pass@server') .then(function (server) { return server.open('db'); }) .then(function (db) { return db.query(query); }) 01. 02. 03. 04. 05. 06. 07. 28
  26. 26. Promise .then(function (view) { return fetchRows(view); }, function handleError(err) { console.error(err); }) // ... Меньше шума, обработка ошибок в одном месте 01. 02. 03. 04. 05. 29
  27. 27. Абстракция над обещанными данными ● Обещание можно сдержать, а можно не выполнять ● Состояние изменяется только 1 раз ● Результат сохраняется ● Цепочка обещаний ● Можно пообещать нескольким 30
  28. 28. Реализация Promise var Promise = function () { this._value = null; this.isFulfilled = false; // ok this.isRejected = false; // fail this.isResolved = false; // ok || fail // ... }; 01. 02. 03. 04. 05. 06. 07. 31
  29. 29. Реализация Promise Promise.prototype = { // @return {Promise} then: function (onFulfilled, onRejected) {}, fulfill: function (data) {}, reject: function (error) {} }; 01. 02. 03. 04. 05. 06. 32
  30. 30. Использование Promise // @param {Number} time // @return {Promise} function timeout(time) { var promise = new Promise(); setTimeout(promise.fulfill, time); return promise; } 01. 02. 03. 04. 05. 06. 07. 33
  31. 31. Пример timeout timeout(1000) .then(function () { console.log('first'); return timeout(1000); }) .then(console.log.bind(console, 'second!')); 01. 02. 03. 04. 05. 06. Run 34
  32. 32. Пример timeout timeout(1000) .then(randomLog) .then(console.log.bind(console, 'done!')); function randomLog() { var rnd = Math.random(); console.log(rnd); if (rnd < 0.5) return timeout(2000); } 01. 02. 03. 04. 05. 06. 07. 08. Run 35
  33. 33. Promise ● Не хак и не магия ● Единый интерфейс всех промисов ● Меньше шума в коде ● Разделение логики на шаги ● ... ● PROFIT! 36
  34. 34. Трюки с Promise
  35. 35. Склеивание Promise // $.when - агрегатор Promise // Результат не раньше, чем через 1с $.when($.get('/'), $.get('/?'), timeout(1000)) .then(function (res) { console.log(res[0].length + res[1].length); }); 01. 02. 03. 04. 05. 06. Run 38
  36. 36. Повтор Promise new Attempt(get404, repeat3Times) .then(ok, epicFail, progress); function get404() { return $.get('/404'); } function repeat3Times(err, num) { if (num < 4) return 1000; } 01. 02. 03. 04. 05. 06. 07. 08. Run 39
  37. 37. Прозрачный кэш с Promise var cache; function request() { return cache ? cache : cache = $.get('/'); } request().then(function (html) { console.log(html.length); }); 01. 02. 03. 04. 05. 06. 07. Run 40
  38. 38. Promise уже рядом! ● Браузер – $.Deferred – $.when, $.ajax, $.get, $.post, ... ● Node.js – Q: q-io – Vow: vow-fs, vow-asker ● DOM Promises! WHATWG Promise Spec 41
  39. 39. Generators ● Решение проблем асинхронности будущего ● Оператор yield «Ставит выполнение кода на паузу» ● Когда? – Node.js 0.11.x c --harmony-generators – Браузеры на V8 3.19 c --harmony-generators – Firefox 2+ (старый синтаксис) ● Можно транслировать в ES5, но лучше это не делать... 43
  40. 40. Generators var co = require('co'); co(function *() { var server = yield login('user:pass@server'), db = yield server.open('db'), view = yield db.query(query); }); Скоро на экранах ваших IDE 01. 02. 03. 04. 05. 06. 44
  41. 41. yield vs then?
  42. 42. Generators и Promise ● Именно «и», а не «VS» ● Используем вместе – Библиотека Q – Библиотека co ● С Generators код еще чище! ● Обработка ошибок с try/catch! 46
  43. 43. Используйте Promise! ● Готов к использованию сегодня! ● Единый интерфейс ● Стандарт Promise/A+ ● Структурирует код ● Меньше шума в коде ● Куча библиотек: Vow, Q, jQuery 47
  44. 44. Promise — это не больно! Михаил Давыдов JavaScript-разработчик @azproduction 50
  45. 45. Почитать ● Примеры с презентации ● Promises/A+ ● Differences from Promises/A ● Design of Q library (настоятельно рекомендую) ● Iterators & Generators ● A Study on Solving Callbacks with JavaScript Generators ● A Closer Look at Generators Without Promises 51
  46. 46. clck.ru/8i9pr

×