110
How to stop debugging asynchronous code and start living Andrey Salomatin BerlinJS 18.06.2015

How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

Embed Size (px)

Citation preview

Page 1: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

How to stop debugging asynchronous code

and start living

Andrey Salomatin BerlinJS

18.06.2015

Page 2: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

Schlecht!Script

Page 3: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

Schlecht!Script

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

f1*red(a, b)

function f2*blue(c) {…}

f2*blue(c)

3

Functions have colors

Page 4: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

Schlecht!Script

/* OK! */

function outer*blue() {

inner*blue()

}

4

Blue functions can only call other blue functions

/* NOT OK! */

function outer*blue() {

inner*red()

}

Page 5: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

Schlecht!Script

/* OK! */

function outer*red() {

inner2*red()

}

5

Red functions can call red and blue functions

/* OK! */

function outer*red() {

inner2*blue()

}

Page 6: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

Implementing and calling red functions is painful!

6

Page 7: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

Schlecht!Script7

Red functions can only be named in german!

/* Can’t be interpreted */

function authUser*red() {…}

function getName*red() {…}

Page 8: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

Schlecht!Script8

Red functions can only be named in german!

/* RICHTIG! */

function benutzerAutorisierung!*rot() {…}

function nameErhalten!*rot() {…}

Page 9: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

How to write in Schlecht!Script?

9

Page 10: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

JavaScript

Page 11: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

JavaScript extends

Schlecht!Script

11

Page 12: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

Dealing with asynchronous functions

is a nightmare

12

Page 13: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

JavaScript

• if/else, for, return don’t work

• No try/catch • Abstraction is broken

13

Dealing with asynchronous functions is painful

Page 14: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

// execute in sequence

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

if (shouldProcess(i)) {

results.push(process(i));

}

}

14

JavaScript

if/for synchronously

Page 15: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

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 asynchronously

Page 16: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

JavaScript

• if/else, for, return don’t work

• No try/catch • Abstraction is broken

16

Dealing with asynchronous functions is painful

Page 17: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

Asynchronous codein JavaScript

17

Page 18: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

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

Productive Mobile MoscowJS RadioJS

18

@filipovskii

Page 19: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

Asynchronous

Page 20: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

Multiple events

Single operation

20

Asynchronous: two cases

Page 21: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS
Page 22: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

Control

22

Page 23: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

Exceptions

23

Page 24: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

Unified interface

24

Page 25: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS
Page 26: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

• Handling multiple asynchronous eventsEventEmitterStream

• Handling single asynchronous operation Continuation Passing Style PromisesCoroutines

26

ES6

Page 27: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

• Handling multiple asynchronous eventsAsync Generators

• Handling single asynchronous operation Async/Await

27

ES7

Page 28: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

ES6

Page 29: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

Handling multiple asynchronous events

29

Page 30: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

30

Handling multiple asynchronous events

EventEmitter

Stream

Page 31: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

EventEmitter31

Object that emits events

Page 32: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

EventEmitter32

Examples

Browser: XMLHttpRequest

Node: http.Server

Page 33: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

EventEmitter

emitter.addEventListener(eventName, cb);

emitter.removeEventListener(eventName, cb);

33

API

Page 34: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

EventEmitter34

XMLHttpRequest

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

Page 35: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

EventEmitter35

Implementations

Browser + Node:EventEmitter3, Tiny Emitter

Node:Node EventEmitter

Page 36: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

36

Handling multiple asynchronous events

EventEmitter

Stream

Page 37: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

37

EventEmitter

Stream

Handling multiple asynchronous events

Page 38: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

Stream of data

Stream38

Page 39: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

Stream39

Examples

Node: fs.createReadStream(path)

Node: gulp.src(pattern)

Page 40: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

Stream40

Types of streams

stylus files css files css prefixed files

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

Page 41: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

Stream41

source transform transform consumer

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

Types of streams

Page 42: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

42

Page 43: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

Stream43

Implementations

Isomorphic:RxJS, Kefir, Bacon.js

Node:Node Streams

Page 44: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

44

EventEmitter Stream

Handling multiple asynchronous events

Page 45: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

45

Control

Excpetions

Unified Interface

EventEmitter, Stream

Page 46: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

Asynchronous operations

46

Page 47: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

47

Asynchronous operations

Continuation Passing Style Promises

Coroutines

Page 48: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

Continuation Passing Style48

Examples

Browser:

navigator.geolocation.getCurrentPosition(cb)

Node:

fs.stat(path, cb)

Page 49: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

try {

var user = fetchUser(userId);

var following = fetchFollowingUsers(userId);

var tweets = fetchTweets(following);

handleResult(tweets);

} catch (err) {

handleError(err);

}

49

Continuation Passing Style

Get twitter feed synchronously

Page 50: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

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

});

});

});

50

Continuation Passing Style

Get twitter feed asynchronously

Page 51: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

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

51

Continuation Passing Style

Get twitter feed asynchronously

Page 52: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

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

52

Continuation Passing Style

Holen Sie sich die Band tweets asynchron!

Page 53: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

53Schlecht!Script

Page 54: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

54

Asynchronous operations

Continuation Passing Style

Promises

Coroutines

Page 55: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

55

Continuation Passing Style

Promises

Coroutines

Asynchronous operations

Page 56: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

Object represents asynchronous operation

Promises56

Page 57: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

Promise.prototype.then(successCb, errorCb);

57

API

Promises

Page 58: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

fetchUser(userId)

.then(fetchFollowingUsers)

.then(fetchTweets)

.then(handleResult, handleError);

58

Promises

API

Page 59: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

Promises vs

Continuation Passing Style

59

Page 60: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

60

Implementations

jQuery.Deffered Bluebird RSVP Q

Promises

Page 61: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

61

Continuation Passing Style

Promises

Coroutines

Asynchronous operations

Page 62: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

62

Continuation Passing Style

Promises

Coroutines

Asynchronous operations

Page 63: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

Coroutines63

Page 64: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

Coroutines

function getUserName(userId) {

var user = getUser(userId);

return user.name;

}

64

Stop the Earth!

Page 65: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

Function can be paused and resumed later

65

Coroutines

Page 66: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

function * getUserName (userId) {

var user = yield getUser(userId);

return user.name;

};

66

Generators: step 1 of 3

Coroutines

Page 67: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

function * getUserName (userId) {

var user = yield getUser(userId);

return user.name;

};

67

Coroutines

Generators: step 1 of 3

Page 68: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

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

var user = yield getUser(userId);

return user.name;

});

68

Coroutines

Generators: step 2 of 3

Page 69: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

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

var user = yield getUser(userId);

return user.name;

});

69

Coroutines

Generators: step 2 of 3

Page 70: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

userNamePromise = getUserName(userId);

70

Coroutines

Generators: step 3 of 3

Page 71: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

Using generators for asynchronous code —

is a hack

71

Page 72: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

Using generators for asynchronous code —

is a hack

72

(but I will not tell anyone)

Page 73: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

73

Implementations

Browser + Node:co (generators), task.js (generators)

Node:Fibers

Coroutines

Page 74: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

74

Continuation Passing Style

Promises

Coroutines

Asynchronous operations

Page 75: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

75

Control

Exceptions

Unified Interface

CPS, Promises, Coroutines

Page 76: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

76

ES6

• Handling multiple asynchronous eventsEventEmitterStream

• Handling single asynchronous operation Continuation Passing Style PromisesCoroutines

Page 77: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS
Page 78: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

ES7

Page 79: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

79

ES7

• Handling single asynchronous operation Async/Await

• Handling multiple asynchronous eventsAsync Generators

Page 80: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

80

ES7ES7

• Handling single asynchronous operation Async/Await

• Handling multiple asynchronous eventsAsync Generators

Page 81: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

Async/Await

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

var user = yield getUser(userId);

return user.name;

});

81

Generators

Page 82: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

async function getUserName(userId) {

var user = await getUser(userId);

return user.name;

}

82

Async/Await

Async/Await

Page 83: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

async function getUserName(userId) {

var user = await getUser(userId);

return user.name;

}

83

Async функция

Async/Await

Page 84: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

Asynchronous functions legalized in ES7

84

Async/Await

Page 85: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

85

ES7

• Handling single asynchronous operation Async/Await

• Handling multiple asynchronous eventsAsync Generators

Page 86: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

86

ES7

• Handling single asynchronous operation Async/Await

• Handling multiple asynchronous eventsAsync Generators

Page 87: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

Event subscription for human beings

Async Generators87

Page 88: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

async function doDraw() {

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

draw(ev.clientX, ev.clientY);

}

}

88

DOM Events

Async Generators

Page 89: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

async function doDraw() {

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

draw(ev.clientX, ev.clientY);

}

}

89

Async Generators

DOM Events

Page 90: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

doDrawPromise = doDraw();

90

Async Generators

DOM Events

Page 91: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

async function *filterWSMessages(ws) {

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

if (isValid(msg)) yield msg;

}

}

91

WebSocket messages

Async Generators

Page 92: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

async function *filterWSMessages(ws) {

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

if (isValid(msg)) yield msg;

}

}

92

WebSocket messages

Async Generators

Page 93: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

??? = filterWSMessages(ws);

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

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

93

What does Async Generator return?

Async Generators

Page 94: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

messagesObservable = filterWSMessages(ws);

eventsObservable = observe(win, 'mousemove');

eventsObservable = observe(ws, 'message');

94

Async Generators

What does Async Generator return?

Page 95: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

Observables

Streamsaka

Page 96: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

96

ES7

• Handling single asynchronous operation Async/Await

• Handling multiple asynchronous eventsAsync Generators

Page 97: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

ES6 and ES7: asynchronous operations

97

Page 98: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

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

});

});

});

98

ES6 and ES7

Get twitter feed: CPS

Page 99: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

fetchUser(userId)

.then(fetchFollowingUsers)

.then(fetchTweets)

.then(handleResult, handleError);

99

Get twitter feed: Promise

ES6 and ES7

Page 100: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

try {

var user = await fetchUser(userId);

var following = await fetchFollowingUsers(userId);

var tweets = await fetchTweets(following);

handleResult(tweets);

} catch (err) {

handleError(err);

}

100

Get twitter feed: Async/Await

ES6 and ES7

Page 101: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

ES6 and ES7: handling multiple events

101

Page 102: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

var handler = function(ev) {

if (canDraw(ev)) {

draw(ev.clientX, ev.clientY);

}

};

window.addEventListener('mousemove', handler);

window.removeEventListener('mousemove', handler); // later

102

DOM events: EventEmitter

ES6 and ES7

Page 103: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

Kefir.fromEvent(window, 'mousemove')

.filter(canDraw)

.onValue(function(ev) {

draw(ev.clientX, ev.clientY)

})

.end(); // later

103

DOM events: Stream

ES6 and ES7

Page 104: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

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

if (canDraw(ev)) {

draw(ev.clientX, ev.clientY);

}

}

104

DOM events: Async Generators

ES6 and ES7

Page 105: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

How to stop debugging asynchronous code

and start living

105

Page 106: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

Define the case

106

Page 107: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

Consider restrictions

107

Page 108: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

Use best practices

108

Page 109: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

Schlecht!Script?

Page 110: How to stop debugging asynchronous code and start living, Andrey Salomatin, BerlinJS

Thank you!

Andrey Salomatin @filipovskii

BerlinJS 18.06.2015