The Evolution of Asynchronous Javascript - Alessandro Cinelli - Codemotion Milan 2016

163
THE EVOLUTION OF ASYNCHRONOUS JAVASCRIPT @cirpo

Transcript of The Evolution of Asynchronous Javascript - Alessandro Cinelli - Codemotion Milan 2016

THE EVOLUTION OF ASYNCHRONOUS

JAVASCRIPT

@cirpo

@cirpo

Dev lead at

now & later

ASYNCRONY

the core of asynchronous programming is the relationship between

the now and later parts of your program

ASYNCRONY

how to express, manage and

manipulate

program behaviours

over a period of time?

CONCURRENCY MODEL

AND

EVENT LOOP

stack

queue

heap

A JS runtime contains a message queue, which is a list of messages to be processed.

QUEUE

A JS runtime contains a message queue, which is a list of messages to be processed.

To each message is associated a function.

QUEUE

A JS runtime contains a message queue, which is a list of messages to be processed.

To each message is associated a function.

When the stack is empty, a message is taken out of the queue and processed.

QUEUE

EVENT LOOP

events

eventloop

net

filesystem

event queue thread pool

JS IS NON BLOCKING

JS unlike a lot of other languages, never blocks

Handling I/O is typically performed via events and callbacks

When the application is waiting for an IndexedDB query to return or an XHR request to return, it can still process other things like user input

JS IS NON BLOCKING

Node.js is great for Input/Output processing but not optimised for CPU-bound work like performing a large amount of calculations.

JS IS NON BLOCKING

Up until recently (ES2015), JS itself has actually

never had any direct notion of asynchrony built into it

JS runs inside a hosting environment (the browser/nodejs)

The event loop is handled by it

most devs new to JS have issues with the fact that later doesn’t happen strictly and immediately after now

ASYNCRONY

ASYNCRONY

ASYNC IS GREAT

BUT CAN BE HARD

SEQUENTIAL BRAIN

SEQUENTIAL BRAIN

put aside involuntary, subconscious, automatic brain functions

we are not multitasker

can we do that?

yes… but we are blocking

WHAT IF WAITING WERE

JUST AS EASY AS

BLOCKING?

BLOCK

BLOCK

=

BLOCK

PULL

=

WHEN YOU BLOCK,

YOU “PULL” A VALUE

BLOCK

PULL

=

CALLBACK

PIRAMID OF DOOM!

CALLBACK HELL!

BULLSHIT

HOW TO AVOID POD

HOW TO AVOID POD

ASYNC CALLBACK

ASYNC CALLBACK

=

ASYNC CALLBACK

PUSH

=

ASYNC CALLBACK

PUSH

=

LOSS OF CONTROL

FLOW

LOSS OF ERROR

HANDLING

INVERSION

OF

CONTROL

“Don't call us, we'll call you”

INVERSION OF CONTROL

INVERSION OF CONTROL

what if it’s a third party call not under our control?

INVERSION OF CONTROL

INVERSION OF CONTROL

what if it’s never called?

INVERSION OF CONTROL

what if it’s never called?

what if it’s called too early?

INVERSION OF CONTROL

what if it’s never called?

what if it’s called too early?

what if it’s called too late?

meh.

HOW CAN YOU TELL IF

IT’S AN

ASYNC CALL?

meh.

Callbacks are the fundamental unit of asynchrony in JS.

I <3 callbacks

Callbacks are the fundamental unit of asynchrony in JS.

But they’re not enough for the evolving landscape of async programming as JS

matures.

I <3 callbacks

WHAT IF WAITING WERE

JUST AS EASY AS

BLOCKING?

PROMISES

PROMISESA promise represents a proxy for a value not

necessarily known when the promise is created.

PROMISES

It allows you to associate handlers to an asynchronous action's eventual success value or

failure reason.

A promise represents a proxy for a value not necessarily known when the promise is created.

PROMISES

It allows you to associate handlers to an asynchronous action's eventual success value or

failure reason.

This lets asynchronous methods return values like synchronous methods: instead of the final value,

the asynchronous method returns a promise.

A promise represents a proxy for a value not necessarily known when the promise is created.

PROMISESalways async

PROMISES

http://ecma-international.org/ecma-262/6.0/#sec-jobs-and-job-queues

PROMISESalways async

handled once

PROMISESpending: initial state, not fulfilled or rejected

fulfilled: the operation completed successfully

rejected: meaning that the operation failed

settled: has fulfilled or rejected

PROMISESalways async

handled once

thenable

PROMISES

A promise must provide a then method to access its current or eventual value

.then()

PROMISES.then(function(onFulfilled, onRejected)

)

PROMISESalways async

handled once

thenable

returns a promise

PROMISES

can return a promise

.then()

PROMISES

.then()

.then()

.then()

PROMISES

.catch()

Talk is cheap, show me the code

PROMISES

PROMISES

PROMISEScontrol flow

PROMISEScontrol flow

PROMISES

inversion of control

control flow

PROMISES

inversion of control

control flow

PROMISES

inversion of control

error handling

control flow

PROMISES

inversion of control

error handling

control flow

PROMISES

inversion of control

async or sync?

error handling

control flow

PROMISES

inversion of control

async or sync?

error handling

control flow

WIN!

BUT …

PROMISE HELL!

AVOID PROMISE HELL!

AVOID PROMISE HELL!

DON’T USE PROMISES

FOR CONTROL FLOW

YOUR CODEBASE THEN

BECOMES

PROMISE DEPENDANT

USING PROMISES

EVERYWHERE

IMPACTS ON THE DESIGN

TO PROMISE OR TO

CALLBACK?

IF YOU HAVE A

LIBRARY, SUPPORT BOTH

SINGLE VALUE

SINGLE RESOLUTION

BAD FOR STREAMS

SINGLE RESOLUTION

PERFORMANCES?

PERFORMANCES

Promises are slower compared to callbacks

You don’t get rid of callbacks, they just orchestrate callbacks in a trustable way

PERFORMANCES

Promises are slower compared to callbacks

You don’t get rid of callbacks, they just orchestrate callbacks in a trustable way99.9% of the time you

won’t feel it

PERFORMANCES

PROMISES

WHAT IF WAITING WERE

JUST AS EASY AS

BLOCKING?

GENERATORS

GENERATORS

A new type of function that does’t not behave with the run-to-completion behaviour

GENERATORS

GENERATORS1 constructing the iterator, not executing

2 starts the iterator

GENERATORS1 constructing the iterator, not executing

2 starts the iterator

GENERATORS1 constructing the iterator, not executing

2 starts the iterator

4 resume the iterator

3 pause the iterator

GENERATORS1 constructing the iterator, not executing

2 starts the iterator

4 resume the iterator

3 pause the iterator

GENERATORS

with the yield where are pausing

GENERATORS

A.K.A “BLO

CKING”!

with the yield where are pausing

GENERATORS

GENERATORS

iterator is just one side…

GENERATORS

the other side is an ”observable”

GENERATORS

GENERATORS

GENERATORS

GENERATORS

GENERATORS

GENERATORS

we can block

we can pull values

we can push values

GENERATORS

GENERATORS

+

PROMISES

the iterator should listen for the promise to resolve (or reject)

then either resume the generator with the fulfilment message (or throw an error into the generator with the rejection reason)

GENERATORS + PROMISES

GENERATORS + PROMISES

GENERATORS + PROMISES

npm install co

GENERATORS + PROMISES

co(getTotal)

BUT…

ES2017to the rescue!

async/await

async/await

npm install -g babel-cli

babel awesome_code.es2017 -o awesome_code.js

node awesome_code.js

//add it either to .babelrc or package.json{ "plugins": ["transform-async-to-generator"]}

npm install babel-plugin-transform-async-to-generator

STREAMS

CHOOSE YOUR CONCURRENCY MODEL

callbacks

async/await

A BIG THANKS TOKyle Simpson (@getify)

github.com/getify/You-Dont-Know-JS

THANK YOU!