how to stop debugging asynchronous code and start living, andrey salomatin, berlinjs

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

Upload: moscowjs

Post on 04-Aug-2015

194 views

Category:

Software


1 download

TRANSCRIPT

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