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

Post on 16-Jul-2015

6.417 Views

Category:

Presentations & Public Speaking

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

Schlecht!Script

Schlecht!Script

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

f1*red(a, b)

function f2*blue(c) {…}

f2*blue(c)

3

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

Schlecht!Script

/* OK! */

function outer*blue() {

inner*blue()

}

4

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

/* NOT OK! */

function outer*blue() {

inner*red()

}

Schlecht!Script

/* OK! */

function outer*red() {

inner2*red()

}

5

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

/* OK! */

function outer*red() {

inner2*blue()

}

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

6

Schlecht!Script7

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

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

function authUser*red() {…}

function getName*red() {…}

Schlecht!Script8

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

/* RICHTIG! */

function benutzerAutorisierung!*rot() {…}

function nameErhalten!*rot() {…}

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

9

JavaScript

JavaScript extends

Schlecht!Script

11

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

12

JavaScript

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

13

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

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

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

if (shouldProcess(i)) {

results.push(process(i));

}

}

14

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

JavaScript

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

JavaScript

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

16

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

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

17

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

Productive Mobile MoscowJS RadioJS

18

@filipovskii

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

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

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

20

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

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

Контроля

22

Исключений

23

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

24

25

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

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

EventEmitter Stream

Async Generators (ES7)

27

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

Continuation Passing Style Promises

Coroutines Async/Await (ES7)

28

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

ES6

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

событий

30

31

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

EventEmitter

Stream

EventEmitter32

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

EventEmitter33

Примеры

Browser: XMLHttpRequest

Node: http.Server

EventEmitter

emitter.addEventListener(eventName, cb);

emitter.removeEventListener(eventName, cb);

34

API

EventEmitter35

События XMLHttpRequest

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

EventEmitter36

Реализации

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

Node:Node EventEmitter

37

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

EventEmitter

Stream

38

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

EventEmitter

Stream

Поток данных

Stream39

Stream40

Примеры

Node: fs.createReadStream(path)

Node: gulp.src(pattern)

Stream41

Типы потоков

stylus files css files css prefixed files

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

Stream42

Типы потоков

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

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

43

Stream44

Реализации

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

Node:Node Streams

45

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

EventEmitter Stream

46

Контроль

Исключения

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

EventEmitter, Stream

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

47

48

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

Continuation Passing Style Promises

Coroutines

Continuation Passing Style49

Примеры

Browser:

navigator.geolocation.getCurrentPosition(cb)

Node:

fs.stat(path, cb)

try {

var user = fetchUser(userId);

var following = fetchFollowingUsers(userId);

var tweets = fetchTweets(following);

handleResult(tweets);

} catch (err) {

handleError(err);

}

50

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

Continuation Passing Style

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

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

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

54Schlecht!Script

55

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

Continuation Passing Style

Promises

Coroutines

56

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

Continuation Passing Style

Promises

Coroutines

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

Promises57

Promises

Promise.prototype.then(successCb, errorCb);

58

API

Promises

fetchUser(userId)

.then(fetchFollowingUsers)

.then(fetchTweets)

.then(handleResult, handleError);

59

API

Promises vs

Continuation Passing Style

60

Promises61

Реализации

jQuery.Deffered Bluebird RSVP Q

62

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

Continuation Passing Style

Promises

Coroutines

63

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

Continuation Passing Style

Promises

Coroutines

Coroutines64

Coroutines

function getUserName(userId) {

var user = getUser(userId);

return user.name;

}

65

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

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

позже

Coroutines66

Coroutines

function * getUserName (userId) {

var user = yield getUser(userId);

return user.name;

};

67

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

Coroutines

function * getUserName (userId) {

var user = yield getUser(userId);

return user.name;

};

68

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

Coroutines

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

var user = yield getUser(userId);

return user.name;

});

69

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

Coroutines

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

var user = yield getUser(userId);

return user.name;

});

70

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

Coroutines

userNamePromise = getUserName(userId);

71

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

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

это хак

72

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

это хак

73

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

Coroutines74

Реализации

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

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

75

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

Continuation Passing Style

Promises

Coroutines

76

Контроль

Исключения

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

CPS, Promises, Coroutines

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

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

77

ES6

ES7

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

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

80

ES7

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

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

81

ES7

Async/Await

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

var user = yield getUser(userId);

return user.name;

});

82

Генераторы

Async/Await

async function getUserName(userId) {

var user = await getUser(userId);

return user.name;

}

83

Async/Await

Async/Await

async function getUserName(userId) {

var user = await getUser(userId);

return user.name;

}

84

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

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

Async/Await85

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

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

86

ES7

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

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

87

ES7

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

Async Generators88

Async Generators

async function doDraw() {

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

draw(ev.clientX, ev.clientY);

}

}

89

События DOM

Async Generators

async function doDraw() {

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

draw(ev.clientX, ev.clientY);

}

}

90

События DOM

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

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

91

ES7

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

92

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

fetchUser(userId)

.then(fetchFollowingUsers)

.then(fetchTweets)

.then(handleResult, handleError);

94

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

ES6 и ES7

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

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

96

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

Kefir.fromEvent(window, 'mousemove')

.filter(canDraw)

.onValue(function(ev) {

draw(ev.clientX, ev.clientY)

})

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

98

DOM события: Stream

ES6 и ES7

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

if (canDraw(ev)) {

draw(ev.clientX, ev.clientY);

}

}

99

DOM события: Async Generators

ES6 и ES7

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

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

100

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

101

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

102

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

103

Schlecht!Script?

Спасибо!

bit.ly/async-js

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

Frontend DevConf, Минск 18.04.2015

top related