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
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
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
SEQUENTIAL BRAIN
put aside involuntary, subconscious, automatic brain functions
we are not multitasker
yes… but we are blocking
WHAT IF WAITING WERE
JUST AS EASY AS
BLOCKING?
WHEN YOU BLOCK,
YOU “PULL” A VALUE
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?
HOW CAN YOU TELL IF
IT’S AN
ASYNC CALL?
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?
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
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
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 RESOLUTION
BAD FOR STREAMS
SINGLE RESOLUTION
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
WHAT IF WAITING WERE
JUST AS EASY AS
BLOCKING?
GENERATORS
A new type of function that does’t not behave with the run-to-completion behaviour
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
iterator is just one side…
GENERATORS
the other side is an ”observable”
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)
ES2017to the rescue!
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
CHOOSE YOUR CONCURRENCY MODEL
callbacks
async/await
A BIG THANKS TOKyle Simpson (@getify)
github.com/getify/You-Dont-Know-JS