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

Post on 04-Aug-2015

192 Views

Category:

Software

1 Downloads

Preview:

Click to see full reader

TRANSCRIPT

How to stop debugging asynchronous code

and start living

Andrey Salomatin BerlinJS

18.06.2015

Schlecht!Script

Schlecht!Script

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

f1*red(a, b)

function f2*blue(c) {…}

f2*blue(c)

3

Functions have colors

Schlecht!Script

/* OK! */

function outer*blue() {

inner*blue()

}

4

Blue functions can only call other blue functions

/* NOT OK! */

function outer*blue() {

inner*red()

}

Schlecht!Script

/* OK! */

function outer*red() {

inner2*red()

}

5

Red functions can call red and blue functions

/* OK! */

function outer*red() {

inner2*blue()

}

Implementing and calling red functions is painful!

6

Schlecht!Script7

Red functions can only be named in german!

/* Can’t be interpreted */

function authUser*red() {…}

function getName*red() {…}

Schlecht!Script8

Red functions can only be named in german!

/* RICHTIG! */

function benutzerAutorisierung!*rot() {…}

function nameErhalten!*rot() {…}

How to write in Schlecht!Script?

9

JavaScript

JavaScript extends

Schlecht!Script

11

Dealing with asynchronous functions

is a nightmare

12

JavaScript

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

• No try/catch • Abstraction is broken

13

Dealing with asynchronous functions is painful

// execute in sequence

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

if (shouldProcess(i)) {

results.push(process(i));

}

}

14

JavaScript

if/for synchronously

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

JavaScript

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

• No try/catch • Abstraction is broken

16

Dealing with asynchronous functions is painful

Asynchronous codein JavaScript

17

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

Productive Mobile MoscowJS RadioJS

18

@filipovskii

Asynchronous

Multiple events

Single operation

20

Asynchronous: two cases

Control

22

Exceptions

23

Unified interface

24

• Handling multiple asynchronous eventsEventEmitterStream

• Handling single asynchronous operation Continuation Passing Style PromisesCoroutines

26

ES6

• Handling multiple asynchronous eventsAsync Generators

• Handling single asynchronous operation Async/Await

27

ES7

ES6

Handling multiple asynchronous events

29

30

Handling multiple asynchronous events

EventEmitter

Stream

EventEmitter31

Object that emits events

EventEmitter32

Examples

Browser: XMLHttpRequest

Node: http.Server

EventEmitter

emitter.addEventListener(eventName, cb);

emitter.removeEventListener(eventName, cb);

33

API

EventEmitter34

XMLHttpRequest

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

EventEmitter35

Implementations

Browser + Node:EventEmitter3, Tiny Emitter

Node:Node EventEmitter

36

Handling multiple asynchronous events

EventEmitter

Stream

37

EventEmitter

Stream

Handling multiple asynchronous events

Stream of data

Stream38

Stream39

Examples

Node: fs.createReadStream(path)

Node: gulp.src(pattern)

Stream40

Types of streams

stylus files css files css prefixed files

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

Stream41

source transform transform consumer

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

Types of streams

42

Stream43

Implementations

Isomorphic:RxJS, Kefir, Bacon.js

Node:Node Streams

44

EventEmitter Stream

Handling multiple asynchronous events

45

Control

Excpetions

Unified Interface

EventEmitter, Stream

Asynchronous operations

46

47

Asynchronous operations

Continuation Passing Style Promises

Coroutines

Continuation Passing Style48

Examples

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

}

49

Continuation Passing Style

Get twitter feed synchronously

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

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

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!

53Schlecht!Script

54

Asynchronous operations

Continuation Passing Style

Promises

Coroutines

55

Continuation Passing Style

Promises

Coroutines

Asynchronous operations

Object represents asynchronous operation

Promises56

Promise.prototype.then(successCb, errorCb);

57

API

Promises

fetchUser(userId)

.then(fetchFollowingUsers)

.then(fetchTweets)

.then(handleResult, handleError);

58

Promises

API

Promises vs

Continuation Passing Style

59

60

Implementations

jQuery.Deffered Bluebird RSVP Q

Promises

61

Continuation Passing Style

Promises

Coroutines

Asynchronous operations

62

Continuation Passing Style

Promises

Coroutines

Asynchronous operations

Coroutines63

Coroutines

function getUserName(userId) {

var user = getUser(userId);

return user.name;

}

64

Stop the Earth!

Function can be paused and resumed later

65

Coroutines

function * getUserName (userId) {

var user = yield getUser(userId);

return user.name;

};

66

Generators: step 1 of 3

Coroutines

function * getUserName (userId) {

var user = yield getUser(userId);

return user.name;

};

67

Coroutines

Generators: step 1 of 3

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

var user = yield getUser(userId);

return user.name;

});

68

Coroutines

Generators: step 2 of 3

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

var user = yield getUser(userId);

return user.name;

});

69

Coroutines

Generators: step 2 of 3

userNamePromise = getUserName(userId);

70

Coroutines

Generators: step 3 of 3

Using generators for asynchronous code —

is a hack

71

Using generators for asynchronous code —

is a hack

72

(but I will not tell anyone)

73

Implementations

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

Node:Fibers

Coroutines

74

Continuation Passing Style

Promises

Coroutines

Asynchronous operations

75

Control

Exceptions

Unified Interface

CPS, Promises, Coroutines

76

ES6

• Handling multiple asynchronous eventsEventEmitterStream

• Handling single asynchronous operation Continuation Passing Style PromisesCoroutines

ES7

79

ES7

• Handling single asynchronous operation Async/Await

• Handling multiple asynchronous eventsAsync Generators

80

ES7ES7

• Handling single asynchronous operation Async/Await

• Handling multiple asynchronous eventsAsync Generators

Async/Await

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

var user = yield getUser(userId);

return user.name;

});

81

Generators

async function getUserName(userId) {

var user = await getUser(userId);

return user.name;

}

82

Async/Await

Async/Await

async function getUserName(userId) {

var user = await getUser(userId);

return user.name;

}

83

Async функция

Async/Await

Asynchronous functions legalized in ES7

84

Async/Await

85

ES7

• Handling single asynchronous operation Async/Await

• Handling multiple asynchronous eventsAsync Generators

86

ES7

• Handling single asynchronous operation Async/Await

• Handling multiple asynchronous eventsAsync Generators

Event subscription for human beings

Async Generators87

async function doDraw() {

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

draw(ev.clientX, ev.clientY);

}

}

88

DOM Events

Async Generators

async function doDraw() {

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

draw(ev.clientX, ev.clientY);

}

}

89

Async Generators

DOM Events

doDrawPromise = doDraw();

90

Async Generators

DOM Events

async function *filterWSMessages(ws) {

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

if (isValid(msg)) yield msg;

}

}

91

WebSocket messages

Async Generators

async function *filterWSMessages(ws) {

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

if (isValid(msg)) yield msg;

}

}

92

WebSocket messages

Async Generators

??? = filterWSMessages(ws);

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

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

93

What does Async Generator return?

Async Generators

messagesObservable = filterWSMessages(ws);

eventsObservable = observe(win, 'mousemove');

eventsObservable = observe(ws, 'message');

94

Async Generators

What does Async Generator return?

Observables

Streamsaka

96

ES7

• Handling single asynchronous operation Async/Await

• Handling multiple asynchronous eventsAsync Generators

ES6 and ES7: asynchronous operations

97

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

fetchUser(userId)

.then(fetchFollowingUsers)

.then(fetchTweets)

.then(handleResult, handleError);

99

Get twitter feed: Promise

ES6 and ES7

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

ES6 and ES7: handling multiple events

101

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

Kefir.fromEvent(window, 'mousemove')

.filter(canDraw)

.onValue(function(ev) {

draw(ev.clientX, ev.clientY)

})

.end(); // later

103

DOM events: Stream

ES6 and ES7

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

if (canDraw(ev)) {

draw(ev.clientX, ev.clientY);

}

}

104

DOM events: Async Generators

ES6 and ES7

How to stop debugging asynchronous code

and start living

105

Define the case

106

Consider restrictions

107

Use best practices

108

Schlecht!Script?

Thank you!

Andrey Salomatin @filipovskii

BerlinJS 18.06.2015

top related