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

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

on

  • 1,392 views

Асинхронность в JavaScript-приложениях – обычное дело. Любой обмен данными – асинхронный, что HTTP, что чтение ...

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

Statistics

Views

Total Views
1,392
Views on SlideShare
551
Embed Views
841

Actions

Likes
0
Downloads
4
Comments
0

4 Embeds 841

http://tech.yandex.ru 678
http://events.yandex.ru 90
https://tech.yandex.ru 72
http://news.google.com 1

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

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

    • 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', function (err, db) { if (err) return cb(err); db.query(query, function (err, view) {}); }); }); 01. 02. 03. 04. 05. 06. 07. 10
    • Параллельные запросы 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
    • Шум 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
    • Шум ● Статус ошибки ● Однообразная обработка ошибки ● Глубина вложенности 13
    • Сложно отменить действие 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
    • Несколько обработчиков query(query1, function (err, view) {}); query(query2, function (err, view) {}); query(query3, function (err, view) {}); 3 запроса — 3 попытки логина. Для кэша нужно еще дописать код. 01. 02. 03. 15
    • Делегирование результата function uberQueryGenerator(data) { // Готовим queryFromData return query(queryFromData); } function uberQueryGenerator(data, fn) { query(queryFromData, fn); } 01. 02. 03. 04. 01. 02. 03. 16
    • У callback-ов нет единого интерфейса
    • Нет единого интерфейса ● Последний аргумент ● Свойство конфига или метод – success – complete – done – finish – ??? 18
    • Нет единого интерфейса $('div').animate({}, function () {}); // А можно еще вот так $('div').animate({}, { complete: function () {} }); 01. 02. 03. 04. 05. 19
    • Нет единого интерфейса $.ajax({ url: url success: function () {} }); $.ajax({ url: url }).done(function () {}); 01. 02. 03. 04. 05. 06. 07. 20
    • Магия
    • Магия ● Step.js ● Streamline.js ● Fibers ● ??? 22
    • 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
    • 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', _], 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
    • Promise ● aka Futures ● Распостранен в других языках ● Стандартизирован Promise/A+ ● Стандарт «Покрыт тестами» Promises/A+ Compliance Test Suite ● Готовые абстракции над fs, http, ... 27
    • 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
    • Promise .then(function (view) { return fetchRows(view); }, function handleError(err) { console.error(err); }) // ... Меньше шума, обработка ошибок в одном месте 01. 02. 03. 04. 05. 29
    • Абстракция над обещанными данными ● Обещание можно сдержать, а можно не выполнять ● Состояние изменяется только 1 раз ● Результат сохраняется ● Цепочка обещаний ● Можно пообещать нескольким 30
    • Реализация 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
    • Реализация Promise Promise.prototype = { // @return {Promise} then: function (onFulfilled, onRejected) {}, fulfill: function (data) {}, reject: function (error) {} }; 01. 02. 03. 04. 05. 06. 32
    • Использование 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
    • Пример 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
    • Пример 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
    • Promise ● Не хак и не магия ● Единый интерфейс всех промисов ● Меньше шума в коде ● Разделение логики на шаги ● ... ● PROFIT! 36
    • Трюки с Promise
    • Склеивание 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
    • Повтор 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
    • Прозрачный кэш с 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
    • Promise уже рядом! ● Браузер – $.Deferred – $.when, $.ajax, $.get, $.post, ... ● Node.js – Q: q-io – Vow: vow-fs, vow-asker ● DOM Promises! WHATWG Promise Spec 41
    • Generators ● Решение проблем асинхронности будущего ● Оператор yield «Ставит выполнение кода на паузу» ● Когда? – Node.js 0.11.x c --harmony-generators – Браузеры на V8 3.19 c --harmony-generators – Firefox 2+ (старый синтаксис) ● Можно транслировать в ES5, но лучше это не делать... 43
    • 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
    • yield vs then?
    • Generators и Promise ● Именно «и», а не «VS» ● Используем вместе – Библиотека Q – Библиотека co ● С Generators код еще чище! ● Обработка ошибок с try/catch! 46
    • Используйте Promise! ● Готов к использованию сегодня! ● Единый интерфейс ● Стандарт Promise/A+ ● Структурирует код ● Меньше шума в коде ● Куча библиотек: Vow, Q, jQuery 47
    • Promise — это не больно! Михаил Давыдов JavaScript-разработчик @azproduction 50
    • Почитать ● Примеры с презентации ● 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
    • clck.ru/8i9pr