«Как перестать отлаживать асинхронные вызовы и начать...

105

Upload: fdconf

Post on 16-Jul-2015

6.417 views

Category:

Presentations & Public Speaking


0 download

TRANSCRIPT

Page 1: «Как перестать отлаживать асинхронные вызовы и начать жить»
Page 2: «Как перестать отлаживать асинхронные вызовы и начать жить»

Schlecht!Script

Page 3: «Как перестать отлаживать асинхронные вызовы и начать жить»

Schlecht!Script

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

f1*red(a, b)

function f2*blue(c) {…}

f2*blue(c)

3

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

Page 4: «Как перестать отлаживать асинхронные вызовы и начать жить»

Schlecht!Script

/* OK! */

function outer*blue() {

inner*blue()

}

4

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

/* NOT OK! */

function outer*blue() {

inner*red()

}

Page 5: «Как перестать отлаживать асинхронные вызовы и начать жить»

Schlecht!Script

/* OK! */

function outer*red() {

inner2*red()

}

5

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

/* OK! */

function outer*red() {

inner2*blue()

}

Page 6: «Как перестать отлаживать асинхронные вызовы и начать жить»

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

6

Page 7: «Как перестать отлаживать асинхронные вызовы и начать жить»

Schlecht!Script7

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

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

function authUser*red() {…}

function getName*red() {…}

Page 8: «Как перестать отлаживать асинхронные вызовы и начать жить»

Schlecht!Script8

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

/* RICHTIG! */

function benutzerAutorisierung!*rot() {…}

function nameErhalten!*rot() {…}

Page 9: «Как перестать отлаживать асинхронные вызовы и начать жить»

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

9

Page 10: «Как перестать отлаживать асинхронные вызовы и начать жить»

JavaScript

Page 11: «Как перестать отлаживать асинхронные вызовы и начать жить»

JavaScript extends

Schlecht!Script

11

Page 12: «Как перестать отлаживать асинхронные вызовы и начать жить»

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

12

Page 13: «Как перестать отлаживать асинхронные вызовы и начать жить»

JavaScript

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

13

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

Page 14: «Как перестать отлаживать асинхронные вызовы и начать жить»

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

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

if (shouldProcess(i)) {

results.push(process(i));

}

}

14

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

JavaScript

Page 15: «Как перестать отлаживать асинхронные вызовы и начать жить»

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

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

JavaScript

Page 16: «Как перестать отлаживать асинхронные вызовы и начать жить»

JavaScript

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

16

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

Page 17: «Как перестать отлаживать асинхронные вызовы и начать жить»

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

17

Page 18: «Как перестать отлаживать асинхронные вызовы и начать жить»

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

Productive Mobile MoscowJS RadioJS

18

@filipovskii

Page 19: «Как перестать отлаживать асинхронные вызовы и начать жить»

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

Page 20: «Как перестать отлаживать асинхронные вызовы и начать жить»

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

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

20

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

Page 21: «Как перестать отлаживать асинхронные вызовы и начать жить»

Чего мы хотим?

Page 22: «Как перестать отлаживать асинхронные вызовы и начать жить»

Контроля

22

Page 23: «Как перестать отлаживать асинхронные вызовы и начать жить»

Исключений

23

Page 24: «Как перестать отлаживать асинхронные вызовы и начать жить»

Единого интерфейса

24

Page 25: «Как перестать отлаживать асинхронные вызовы и начать жить»

25

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

Единого интерфейса

Page 26: «Как перестать отлаживать асинхронные вызовы и начать жить»
Page 27: «Как перестать отлаживать асинхронные вызовы и начать жить»

EventEmitter Stream

Async Generators (ES7)

27

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

Page 28: «Как перестать отлаживать асинхронные вызовы и начать жить»

Continuation Passing Style Promises

Coroutines Async/Await (ES7)

28

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

Page 29: «Как перестать отлаживать асинхронные вызовы и начать жить»

ES6

Page 30: «Как перестать отлаживать асинхронные вызовы и начать жить»

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

событий

30

Page 31: «Как перестать отлаживать асинхронные вызовы и начать жить»

31

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

EventEmitter

Stream

Page 32: «Как перестать отлаживать асинхронные вызовы и начать жить»

EventEmitter32

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

Page 33: «Как перестать отлаживать асинхронные вызовы и начать жить»

EventEmitter33

Примеры

Browser: XMLHttpRequest

Node: http.Server

Page 34: «Как перестать отлаживать асинхронные вызовы и начать жить»

EventEmitter

emitter.addEventListener(eventName, cb);

emitter.removeEventListener(eventName, cb);

34

API

Page 35: «Как перестать отлаживать асинхронные вызовы и начать жить»

EventEmitter35

События XMLHttpRequest

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

Page 36: «Как перестать отлаживать асинхронные вызовы и начать жить»

EventEmitter36

Реализации

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

Node:Node EventEmitter

Page 37: «Как перестать отлаживать асинхронные вызовы и начать жить»

37

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

EventEmitter

Stream

Page 38: «Как перестать отлаживать асинхронные вызовы и начать жить»

38

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

EventEmitter

Stream

Page 39: «Как перестать отлаживать асинхронные вызовы и начать жить»

Поток данных

Stream39

Page 40: «Как перестать отлаживать асинхронные вызовы и начать жить»

Stream40

Примеры

Node: fs.createReadStream(path)

Node: gulp.src(pattern)

Page 41: «Как перестать отлаживать асинхронные вызовы и начать жить»

Stream41

Типы потоков

stylus files css files css prefixed files

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

Page 42: «Как перестать отлаживать асинхронные вызовы и начать жить»

Stream42

Типы потоков

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

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

Page 43: «Как перестать отлаживать асинхронные вызовы и начать жить»

43

Page 44: «Как перестать отлаживать асинхронные вызовы и начать жить»

Stream44

Реализации

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

Node:Node Streams

Page 45: «Как перестать отлаживать асинхронные вызовы и начать жить»

45

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

EventEmitter Stream

Page 46: «Как перестать отлаживать асинхронные вызовы и начать жить»

46

Контроль

Исключения

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

EventEmitter, Stream

Page 47: «Как перестать отлаживать асинхронные вызовы и начать жить»

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

47

Page 48: «Как перестать отлаживать асинхронные вызовы и начать жить»

48

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

Continuation Passing Style Promises

Coroutines

Page 49: «Как перестать отлаживать асинхронные вызовы и начать жить»

Continuation Passing Style49

Примеры

Browser:

navigator.geolocation.getCurrentPosition(cb)

Node:

fs.stat(path, cb)

Page 50: «Как перестать отлаживать асинхронные вызовы и начать жить»

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: «Как перестать отлаживать асинхронные вызовы и начать жить»

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: «Как перестать отлаживать асинхронные вызовы и начать жить»

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);

});

52

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

Continuation Passing Style

Page 53: «Как перестать отлаживать асинхронные вызовы и начать жить»

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

Получить ленту твитов asynchron!

Continuation Passing Style

Page 54: «Как перестать отлаживать асинхронные вызовы и начать жить»

54Schlecht!Script

Page 55: «Как перестать отлаживать асинхронные вызовы и начать жить»

55

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

Continuation Passing Style

Promises

Coroutines

Page 56: «Как перестать отлаживать асинхронные вызовы и начать жить»

56

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

Continuation Passing Style

Promises

Coroutines

Page 57: «Как перестать отлаживать асинхронные вызовы и начать жить»

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

Promises57

Page 58: «Как перестать отлаживать асинхронные вызовы и начать жить»

Promises

Promise.prototype.then(successCb, errorCb);

58

API

Page 59: «Как перестать отлаживать асинхронные вызовы и начать жить»

Promises

fetchUser(userId)

.then(fetchFollowingUsers)

.then(fetchTweets)

.then(handleResult, handleError);

59

API

Page 60: «Как перестать отлаживать асинхронные вызовы и начать жить»

Promises vs

Continuation Passing Style

60

Page 61: «Как перестать отлаживать асинхронные вызовы и начать жить»

Promises61

Реализации

jQuery.Deffered Bluebird RSVP Q

Page 62: «Как перестать отлаживать асинхронные вызовы и начать жить»

62

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

Continuation Passing Style

Promises

Coroutines

Page 63: «Как перестать отлаживать асинхронные вызовы и начать жить»

63

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

Continuation Passing Style

Promises

Coroutines

Page 64: «Как перестать отлаживать асинхронные вызовы и начать жить»

Coroutines64

Page 65: «Как перестать отлаживать асинхронные вызовы и начать жить»

Coroutines

function getUserName(userId) {

var user = getUser(userId);

return user.name;

}

65

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

Page 66: «Как перестать отлаживать асинхронные вызовы и начать жить»

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

позже

Coroutines66

Page 67: «Как перестать отлаживать асинхронные вызовы и начать жить»

Coroutines

function * getUserName (userId) {

var user = yield getUser(userId);

return user.name;

};

67

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

Page 68: «Как перестать отлаживать асинхронные вызовы и начать жить»

Coroutines

function * getUserName (userId) {

var user = yield getUser(userId);

return user.name;

};

68

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

Page 69: «Как перестать отлаживать асинхронные вызовы и начать жить»

Coroutines

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

var user = yield getUser(userId);

return user.name;

});

69

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

Page 70: «Как перестать отлаживать асинхронные вызовы и начать жить»

Coroutines

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

var user = yield getUser(userId);

return user.name;

});

70

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

Page 71: «Как перестать отлаживать асинхронные вызовы и начать жить»

Coroutines

userNamePromise = getUserName(userId);

71

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

Page 72: «Как перестать отлаживать асинхронные вызовы и начать жить»

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

это хак

72

Page 73: «Как перестать отлаживать асинхронные вызовы и начать жить»

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

это хак

73

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

Page 74: «Как перестать отлаживать асинхронные вызовы и начать жить»

Coroutines74

Реализации

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

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

Page 75: «Как перестать отлаживать асинхронные вызовы и начать жить»

75

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

Continuation Passing Style

Promises

Coroutines

Page 76: «Как перестать отлаживать асинхронные вызовы и начать жить»

76

Контроль

Исключения

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

CPS, Promises, Coroutines

Page 77: «Как перестать отлаживать асинхронные вызовы и начать жить»

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

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

77

ES6

Page 78: «Как перестать отлаживать асинхронные вызовы и начать жить»
Page 79: «Как перестать отлаживать асинхронные вызовы и начать жить»

ES7

Page 80: «Как перестать отлаживать асинхронные вызовы и начать жить»

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

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

80

ES7

Page 81: «Как перестать отлаживать асинхронные вызовы и начать жить»

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

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

81

ES7

Page 82: «Как перестать отлаживать асинхронные вызовы и начать жить»

Async/Await

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

var user = yield getUser(userId);

return user.name;

});

82

Генераторы

Page 83: «Как перестать отлаживать асинхронные вызовы и начать жить»

Async/Await

async function getUserName(userId) {

var user = await getUser(userId);

return user.name;

}

83

Async/Await

Page 84: «Как перестать отлаживать асинхронные вызовы и начать жить»

Async/Await

async function getUserName(userId) {

var user = await getUser(userId);

return user.name;

}

84

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

Page 85: «Как перестать отлаживать асинхронные вызовы и начать жить»

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

Async/Await85

Page 86: «Как перестать отлаживать асинхронные вызовы и начать жить»

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

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

86

ES7

Page 87: «Как перестать отлаживать асинхронные вызовы и начать жить»

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

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

87

ES7

Page 88: «Как перестать отлаживать асинхронные вызовы и начать жить»

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

Async Generators88

Page 89: «Как перестать отлаживать асинхронные вызовы и начать жить»

Async Generators

async function doDraw() {

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

draw(ev.clientX, ev.clientY);

}

}

89

События DOM

Page 90: «Как перестать отлаживать асинхронные вызовы и начать жить»

Async Generators

async function doDraw() {

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

draw(ev.clientX, ev.clientY);

}

}

90

События DOM

Page 91: «Как перестать отлаживать асинхронные вызовы и начать жить»

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

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

91

ES7

Page 92: «Как перестать отлаживать асинхронные вызовы и начать жить»

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

92

Page 93: «Как перестать отлаживать асинхронные вызовы и начать жить»

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);

});

});

});

93

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

ES6 и ES7

Page 94: «Как перестать отлаживать асинхронные вызовы и начать жить»

fetchUser(userId)

.then(fetchFollowingUsers)

.then(fetchTweets)

.then(handleResult, handleError);

94

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

ES6 и ES7

Page 95: «Как перестать отлаживать асинхронные вызовы и начать жить»

try {

var user = await fetchUser(userId);

var following = await fetchFollowingUsers(userId);

var tweets = await fetchTweets(following);

handleResult(tweets);

catch (err) {

handleError(err);

}

95

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

ES6 и ES7

Page 96: «Как перестать отлаживать асинхронные вызовы и начать жить»

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

96

Page 97: «Как перестать отлаживать асинхронные вызовы и начать жить»

var handler = function(ev) {

if (canDraw(ev)) {

draw(ev.clientX, ev.clientY);

}

};

window.addEventListener('mousemove', handler);

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

97

DOM события: EventEmitter

ES6 и ES7

Page 98: «Как перестать отлаживать асинхронные вызовы и начать жить»

Kefir.fromEvent(window, 'mousemove')

.filter(canDraw)

.onValue(function(ev) {

draw(ev.clientX, ev.clientY)

})

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

98

DOM события: Stream

ES6 и ES7

Page 99: «Как перестать отлаживать асинхронные вызовы и начать жить»

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

if (canDraw(ev)) {

draw(ev.clientX, ev.clientY);

}

}

99

DOM события: Async Generators

ES6 и ES7

Page 100: «Как перестать отлаживать асинхронные вызовы и начать жить»

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

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

100

Page 101: «Как перестать отлаживать асинхронные вызовы и начать жить»

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

101

Page 102: «Как перестать отлаживать асинхронные вызовы и начать жить»

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

102

Page 103: «Как перестать отлаживать асинхронные вызовы и начать жить»

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

103

Page 104: «Как перестать отлаживать асинхронные вызовы и начать жить»

Schlecht!Script?

Page 105: «Как перестать отлаживать асинхронные вызовы и начать жить»

Спасибо!

bit.ly/async-js

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

Frontend DevConf, Минск 18.04.2015