"Как перестать отлаживать асинхронный код и начать...

111
Как перестать отлаживать асинхронный код и начать жить Андрей Саломатин FrontendConf, Москва 21.05.2015

Upload: moscowjs

Post on 16-Jul-2015

1.015 views

Category:

Software


0 download

TRANSCRIPT

Page 1: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

Как перестать отлаживать асинхронный код и начать жить

Андрей Саломатин FrontendConf, Москва

21.05.2015

Page 2: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

Schlecht!Script

Page 3: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

Schlecht!Script

function f1*red(a, b) {…}

f1*red(a, b)

function f2*blue(c) {…}

f2*blue(c)

3

Функции имеют цвет

Page 4: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

Schlecht!Script

/* OK! */

function outer*blue() {

inner*blue()

}

4

Синие могут вызывать только другие синие функции

/* NOT OK! */

function outer*blue() {

inner*red()

}

Page 5: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

Schlecht!Script

/* OK! */

function outer*red() {

inner2*red()

}

5

Красные могут вызывать и красные и синие функции

/* OK! */

function outer*red() {

inner2*blue()

}

Page 6: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

Писать и вызывать красные функции больно!

6

Page 7: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

Schlecht!Script7

Красные функции нужно называть на немецком!

/* Интерпретатор не поймёт */

function authUser*red() {…}

function getName*red() {…}

Page 8: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

Schlecht!Script8

Красные функции нужно называть на немецком!

/* RICHTIG! */

function benutzerAutorisierung!*rot() {…}

function nameErhalten!*rot() {…}

Page 9: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

Как писать на Schlecht!Script?

9

Page 10: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

JavaScript

Page 11: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

JavaScript extends

Schlecht!Script

11

Page 12: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

Асинхронные функции это боль

12

Page 13: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

JavaScript

• По-другому работают if/else, for, return • Нет try/catch • Ломают абстракцию

13

Асинхронные функции это боль

Page 14: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

// выполнять последовательно

for (var i = 0; i < 10; i++) {

if (shouldProcess(i)) {

results.push(process(i));

}

}

14

JavaScript

if/for синхронно

Page 15: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

function maybeProcess(i) {

if (i >= 10) { return; }

shouldProcess(function(should) {

if (should) {

process(i, function(result) {

results.push(result);

maybeProcess(i++);

});

}

maybeProcess(i++);

});

}

maybeProcess(0);

15

JavaScript

if/for асинхронно

Page 16: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

JavaScript

• Не работают if/then, for и т.д. • Нет try/catch • Ломают абстракцию

16

Асинхронные функции это боль

Page 17: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

Асинхронностьв JavaScript

17

Page 18: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

Андрей Саломатин

Productive Mobile MoscowJS RadioJS

18

@filipovskii

Page 19: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

Асинхронность

Page 20: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

Множество событий

Единичная операция

20

Асинхронность: два сценария

Page 21: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015
Page 22: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

Контроль

22

Page 23: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

Исключения

23

Page 24: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

Единый интерфейс

24

Page 25: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

25

КонтрольИсключения

Единый интерфейс

Page 26: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015
Page 27: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

• Работа с множеством событийEventEmitterStream

• Работа с асинхронными операциямиContinuation Passing Style PromisesCoroutines

27

ES6

Page 28: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

• Работа с множеством событийAsync Generators

• Работа с асинхронными операциямиAsync/Await

28

ES7

Page 29: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

ES6

Page 30: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

Работа с множеством асинхронных

событий

30

Page 31: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

31

Работа с множеством асинхронных событий

EventEmitter

Stream

Page 32: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

EventEmitter32

Объект — источник событий

Page 33: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

EventEmitter33

Примеры

Browser: XMLHttpRequest

Node: http.Server

Page 34: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

EventEmitter

emitter.addEventListener(eventName, cb);

emitter.removeEventListener(eventName, cb);

34

API

Page 35: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

EventEmitter35

События XMLHttpRequest

progress (n) load (1) abort (1) error (1)

Page 36: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

EventEmitter36

Реализации

Браузер + Node:EventEmitter3, Tiny Emitter

Node:Node EventEmitter

Page 37: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

37

Работа с множеством асинхронных событий

EventEmitter

Stream

Page 38: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

38

EventEmitter

Stream

Работа с множеством асинхронных событий

Page 39: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

Поток данных

Stream39

Page 40: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

Stream40

Примеры

Node: fs.createReadStream(path)

Node: gulp.src(pattern)

Page 41: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

Stream41

Типы потоков

stylus files css files css prefixed files

gulp.src('*.styl') stylus() autoprefixer() gulp.dest('dist')

Page 42: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

Stream42

источник преобразование преобразование потребитель

gulp.src('*.styl') stylus() autoprefixer() gulp.dest('dist')

Типы потоков

Page 43: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

43

Page 44: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

Stream44

Реализации

Изоморфные: RxJS, Kefir, Bacon.js

Node:Node Streams

Page 45: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

45

Работа с множеством асинхронных событий

EventEmitter Stream

Page 46: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

46

Контроль

Исключения

Единый интерфейс

EventEmitter, Stream

Page 47: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

Работа с асинхронными операциями

47

Page 48: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

48

Работа с асинхронными операциями

Continuation Passing Style Promises

Coroutines

Page 49: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

Continuation Passing Style49

Примеры

Browser:

navigator.geolocation.getCurrentPosition(cb)

Node:

fs.stat(path, cb)

Page 50: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

try {

var user = fetchUser(userId);

var following = fetchFollowingUsers(userId);

var tweets = fetchTweets(following);

handleResult(tweets);

} catch (err) {

handleError(err);

}

50

Continuation Passing Style

Получить ленту твитов синхронно Получить ленту твитов асинхронно

Page 51: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

fetchUser(userId, function(err, user) {

if (err) { return handleError(err); }

fetchFollowingUsers(user, function(err, following) {

if (err) { return handleError(err); }

fetchTweets(following, function(err, tweets) {

if (err) { return handleError(err); }

handleResult(tweets);

});

});

});

51

Continuation Passing Style

Получить ленту твитов асинхронно

Page 52: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

fetchUser(userId, function(err, user) {

if (err) { return handleError(err); }

fetchFollowingUsers(user, function(err, following) {

if (err) { return handleError(err); }

fetchTweets(following, function(err, tweets) {

if (err) { return handleError(err); }

52

Continuation Passing Style

Получить ленту твитов асинхронно

Page 53: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

holenBenutzer!*rot(userId, function(err, user) {

if (err) { return handleError*blue(err); }

holenFolgendenBenutzer!*rot(user, function(err, following) {

if (err) { return handleError*blue(err); }

holenTweets!*rot(following, function(err, tweets) {

if (err) { return handleError(err); }

53

Continuation Passing Style

Holen Sie sich die Band tweets asynchron!

Page 54: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

54Schlecht!Script

Page 55: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

55

Работа с асинхронными операциями

Continuation Passing Style

Promises

Coroutines

Page 56: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

56

Continuation Passing Style

Promises

Coroutines

Работа с асинхронными операциями

Page 57: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

Объект — асинхронная операция

Promises57

Page 58: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

Promise.prototype.then(successCb, errorCb);

58

API

Promises

Page 59: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

fetchUser(userId)

.then(fetchFollowingUsers)

.then(fetchTweets)

.then(handleResult, handleError);

59

Promises

API

Page 60: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

Promises vs

Continuation Passing Style

60

Page 61: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

61

Реализации

jQuery.Deffered Bluebird RSVP Q

Promises

Page 62: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

62

Continuation Passing Style

Promises

Coroutines

Работа с асинхронными операциями

Page 63: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

63

Continuation Passing Style

Promises

Coroutines

Работа с асинхронными операциями

Page 64: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

Coroutines64

Page 65: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

Coroutines

function getUserName(userId) {

var user = getUser(userId);

return user.name;

}

65

Остановите землю!

Page 66: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

Функция, которую можно приостановить и возобновить

позже

66

Coroutines

Page 67: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

function * getUserName (userId) {

var user = yield getUser(userId);

return user.name;

};

67

Генераторы: шаг 1 из 3

Coroutines

Page 68: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

function * getUserName (userId) {

var user = yield getUser(userId);

return user.name;

};

68

Coroutines

Генераторы: шаг 1 из 3

Page 69: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

getUserName = co.wrap(function * (userId) {

var user = yield getUser(userId);

return user.name;

});

69

Coroutines

Генераторы: шаг 2 из 3

Page 70: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

getUserName = co.wrap(function * (userId) {

var user = yield getUser(userId);

return user.name;

});

70

Coroutines

Генераторы: шаг 2 из 3

Page 71: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

userNamePromise = getUserName(userId);

71

Coroutines

Генераторы: шаг 3 из 3

Page 72: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

Использовать генераторы для асинхронного кода —

это хак

72

Page 73: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

Использовать генераторы для асинхронного кода —

это хак

73

(но я вас не выдам)

Page 74: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

74

Реализации

Браузер + Node (используют транспайлер):co (generators), task.js (generators)

Node (использует транспайлер):Fibers

Coroutines

Page 75: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

75

Continuation Passing Style

Promises

Coroutines

Работа с асинхронными операциями

Page 76: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

76

Контроль

Исключения

Единый интерфейс

CPS, Promises, Coroutines

Page 77: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

Работа с множеством событий: EventEmitter Stream

Работа с асинхронными операциями: CPS Promise Coroutine

77

ES6

Page 78: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015
Page 79: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

ES7

Page 80: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

Работа с асинхронными операциями: Async/Await

Работа с множеством событий: Async Generators

80

ES7

Page 81: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

Работа с асинхронными операциями: Async/Await

Работа с множеством событий: Async Generators

81

ES7ES7

Page 82: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

Async/Await

getUserName = co.wrap(function * (userId) {

var user = yield getUser(userId);

return user.name;

});

82

Генераторы

Page 83: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

async function getUserName(userId) {

var user = await getUser(userId);

return user.name;

}

83

Async/Await

Async/Await

Page 84: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

async function getUserName(userId) {

var user = await getUser(userId);

return user.name;

}

84

Асинхронная функция

Async/Await

Page 85: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

Асинхронные функции легализованы в ES7

85

Async/Await

Page 86: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

Работа с асинхронными операциями: Async/Await

Работа с множеством событий: Async Generators

86

ES7

Page 87: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

Работа с асинхронными операциями: Async/Await

Работа с множеством событий: Async Generators

87

ES7

Page 88: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

Подписка на события для людей

Async Generators88

Page 89: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

async function doDraw() {

for (let ev on observe(win, 'mousemove')) {

draw(ev.clientX, ev.clientY);

}

}

89

События DOM

Async Generators

Page 90: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

async function doDraw() {

for (let ev on observe(win, 'mousemove')) {

draw(ev.clientX, ev.clientY);

}

}

90

Async Generators

События DOM

Page 91: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

doDrawPromise = doDraw();

91

Async Generators

События DOM

Page 92: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

async function *filterWSMessages(ws) {

for (let msg on observe(ws, 'message')) {

if (isValid(msg)) yield msg;

}

}

92

WebSocket сообщения

Async Generators

Page 93: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

async function *filterWSMessages(ws) {

for (let msg on observe(ws, 'message')) {

if (isValid(msg)) yield msg;

}

}

93

WebSocket сообщения

Async Generators

Page 94: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

??? = filterWSMessages(ws);

??? = observe(win, 'mousemove');

??? = observe(ws, 'message');

94

Что возвращает Async Generator?

Async Generators

Page 95: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

messagesObservable = filterWSMessages(ws);

eventsObservable = observe(win, 'mousemove');

eventsObservable = observe(ws, 'message');

95

Async Generators

Что возвращает Async Generator?

Page 96: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

Observables

Streamsaka

Page 97: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

Работа с асинхронными операциями: Async/Await

Работа с множеством событий: Async Generators

97

ES7

Page 98: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

ES6 и ES7: асинхронные операции

98

Page 99: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

fetchUser(userId, function(err, user) {

if (err) { return handleError(err); }

fetchFollowingUsers(user, function(err, following) {

if (err) { return handleError(err); }

fetchTweets(following, function(err, tweets) {

if (err) { return handleError(err); }

handleResult(tweets);

});

});

});

99

ES6 и ES7

Получить ленту твитов: CPS

Page 100: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

fetchUser(userId)

.then(fetchFollowingUsers)

.then(fetchTweets)

.then(handleResult, handleError);

100

Получить ленту твитов: Promise

ES6 и ES7

Page 101: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

try {

var user = await fetchUser(userId);

var following = await fetchFollowingUsers(userId);

var tweets = await fetchTweets(following);

handleResult(tweets);

} catch (err) {

handleError(err);

}

101

Получить ленту твитов: Async/Await

ES6 и ES7

Page 102: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

ES6 и ES7: обработка множества событий

102

Page 103: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

var handler = function(ev) {

if (canDraw(ev)) {

draw(ev.clientX, ev.clientY);

}

};

window.addEventListener('mousemove', handler);

window.removeEventListener('mousemove', handler); // позже

103

DOM события: EventEmitter

ES6 и ES7

Page 104: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

Kefir.fromEvent(window, 'mousemove')

.filter(canDraw)

.onValue(function(ev) {

draw(ev.clientX, ev.clientY)

})

.end(); // позже

104

DOM события: Stream

ES6 и ES7

Page 105: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

for (ev on observe(window, 'mousemove')) {

if (canDraw(ev)) {

draw(ev.clientX, ev.clientY);

}

}

105

DOM события: Async Generators

ES6 и ES7

Page 106: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

Как перестать отлаживать асинхронный

код и начать жить

106

Page 107: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

Определите задачу

107

Page 108: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

Обдумайте ограничения

108

Page 109: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

Используйте лучшие практики

109

Page 110: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

Schlecht!Script?

Page 111: "Как перестать отлаживать асинхронный код и начать жить", Андрей Саломатин, FrontendConf 2015

Спасибо!

bit.ly/async-js

Андрей Саломатин @filipovskii

FrontendConf, Москва 21.05.2015