0:02>> (Phillip Roberts) hello, come in and sit
down.
0:05So for the last session before the afternoon
break, we have Phillip Roberts who works at
0:10Andea and is here from London ‑‑ Scotland.
0:13Edinbrough.
0:14‑‑ wow, ten second memory, he's going
to talk about the vent loop.
0:18If everyone could give Phillip a big brownedder
round of applause.
0:19>> Phillip Roberts: Okay hello everyone, thanks
for coming to the side track, it's awesome
0:21to see it packed out in here.
0:23Can everyone give me a stretch.
0:25I needed to stretch, so I look less weird.
0:32I want to talk about the event loop and what
the heck is the event loop, as in the event
0:37loop inside JavaScript.
0:40So first up, as he said I work for AndYet
which is an awesome little Dev shop in the
0:47US, look us up if you need help with real‑time
stuff.
0:51That's what we're good at.
0:52So, about 18 months ago--I'm a paid professional
JavaScript developer--I thought to myself
1:00how does, like JavaScript actually work?
1:04And I wasn't entirely sure.
1:06I'd heard V8 as a term, chrome's Runtime didn't
really know what that meant, what that did.
1:13I'd heard things like single threaded, you
know obviously I'm using callbacks.
1:16How do callbacks work?
1:18I started a journey of like reading and research
and experimenting in the browser which basically
1:25started like this.
1:26‑‑ I was kind of like JavaScript what
are you.
1:31I'm a single threaded single concurrent language ‑‑
right.
1:36yeah, cool, I have a call stack, an event
loop, a callback queue, and some other APIs
1:41and stuff.
1:43‑‑ rite.
1:44I did not do a computer science degree.
1:45I mean, these words, they're words, so I heard
about V8 and the various Runtimes and different
1:51browsers so I looked to V8 do you have a call
stack, an event loop, a callback queue, and
1:56some other APIs and stuff, I have a call stack
and a heap, I don't know what those other
2:00things are, okay, interesting so basically
18 months passed.
2:10And I think I get this.
2:13(Laughing) and so, this is what I want to
share with you today.
2:16Hopefully this will be useful if you're relatively
new to JavaScript, help you understand why
2:22JavaScript is so weird when you compare it
to other languages you might used why callbacks
2:26are a thing, cause us hell but are required.
2:29And if you're an experienced JavaScript developer
hopefully give you some fresh insights how
2:36the Runtime you're using works so you can
think about it a little better.
2:41So if we look at the JavaScript Runtime itself
like V8 which is the Runtime inside Chrome.
2:51This is a simplified view of what JavaScript
Runtime is.
2:55The heap, where memory allocation happens,
and then there's the call stack, which is
3:02where your stack frames are and all that kind
of stuff, but, if you, like, clone the V8
3:10code base and grep for things like setTimeout
or DOM or HTTP request, they're not in there,
3:18they don't exist in V8, which was a surprise
to me.
3:21It's first thing you use when you start thinking
about async stuff and it's not in the V8 source.
3:28Hmm ... interesting.
3:29So, over this 18 months of discovery I come
to realize this is really, this is really
3:36the bigger picture, this is what I'm hoping
to get you on board with today and understand
3:40what these pieces are, we have the V8 Runtime
but then we have these things called web APIs
3:45which are extra things that the browser provides.
3:48DOM, AJAX, time out, things like that, we
have this mythical event loop and the callback
3:55queue.
3:56I'm sure you've heard some of these terms
before, but maybe you don't quite understand
3:59how these pieces pull together.
4:02So, I'm going to start from the beginning,
some of this will be new, to words might be
4:07new to people, other people will get this.
4:09We're going to quickly move on from here,
bear with me if this is obvious, I think for
4:14a lot of people it's not.
4:16So, JavaScript is a single threaded programming
language, single threaded Runtime, it has
4:21a single call stack.
4:23And it can do one thing at a time, that's
what a single thread means, the program can
4:29run one piece of code at a time.
4:31So, let's try and visualize that just to get
our heads around what that mean, so if I have
4:35some code like this on your left, we've got
a few functions, a function multiplier which
4:41multiplies two numbers, square which calls
multiply with the same number twice, a function
4:47which prints the square of a number of calling
square and then calling console.log and then
4:52at the bottom of our file we actually run
print square, this code all good?
4:56Make sense?
4:57Cool.
4:58So, if we run this, well, I should back up
a step, so the call stack is basically ‑‑
5:04it's a data structure which records basically
where in the program we are, if we step into
5:09a function, we put something on to the stack,
if we return from a function, we pop off the
5:13top of the stack that's all the stack can
do, ‑‑ so if you run this file, there's
5:19kind of a main function, right, like the file
itself, so, we push that on to the stack.
5:23Then we have some function definitions, they're
just like defining the state of the world,
5:28and finally we got to print square, right,
so print square is a function call, so we
5:33push that on to the stack, and immediately
inside print square, push on to the stack,
5:38which calls multiply, now we have a return
statement, we multiply A and B and we return,
5:44when we return we pop something off the stack,
so, pop, multiplier of the stack, returning
5:49to square, return to print square, console.log,
there's no return, it's implicit, because
5:57we got to the end of the function, and we're
done so that's like a visualization of the
6:02call stalk, does that make sense?
6:05(Yes, Phil) even if you haven't thought about
the call stack before, you've come across
6:12it when you've been doing browser‑side development,
so if we have code like this, a function baz
6:18which calls bar, which calls Foo, which throws
an error if we run it in Chrome we see this.
6:27And it prints the stack trace, right, the
state of the stack when that error happened,
6:32so, uncaught error oops Foo, bar, Baz, anonymous
function, which is our main.
6:40Equally, if you've heard the term like blowing
the stack, this is an example of that.
6:46Have a function foo which calls Foo , so what's
going to happen ? We have a function main
6:53which calls foo which calls foo, which calls
foo, which calls foo, and ultimately chrome
7:01says, you probably didn't mean to call foo
16,000 times recursively, I'll just kill things
7:07for you and you can figure out where your
bug lies, right.
7:11So although I may be representing a new side
of the call stack you have some sense of it
7:17in your development practice already.
7:19So, the big question then comes is like what
happens when things are slow?
7:24So, we talk about blocking and blocking behavior
and blocking, there's no strict definition
7:31of what is and didn't blocking, really it's
just code that's slow.
7:36So console.log isn't slow, doing a while loop
from one to ten billion is slow, network requests
7:41are slow.
7:42Image requests are slow.
7:46Things which are slow and on that stack are
what are blocking means.
7:52So heres a little example, so let's say we
have, this is like a fake bit of code, getSynchronous,
7:59right, like jQuery is like, AJAX request.
8:04What would happen if those were synchronous
requests, forget what we know about async
8:07callbacks they're synchronous.
8:10If we go through it like we have, we call
getSync and then we wait, because then we're
8:16doing network request, network is relative
to computers, are slow, hopefully that network
8:22requests completes, we can move on, wait,
move on.
8:28Wait, and, I mean, this network request might
never finish, so ... yeah, I guess I'll go
8:37home.
8:38Finally those three, you know blocking behaviors
complete and we can clear the stack, right.
8:43So in a programming language is single threaded
you're not using threads like say Ruby, that's
8:50what happens, right, we make a network request,
we have to just wait till it's done, because
8:54we have no way of handling that.
8:57Why is this actually a problem?
9:00The problem is because we're running code
in browsers.
9:04So, let's you ‑‑ here we go, okay.
9:11So this is just, this is Chrome, this is the
code I just ran.
9:16Browsers don't give us ‑‑ well they do
give us synchronous AJAX request, I'm faking
9:21this out with a big while loop, because it's
synchronous, I basically while loop for five
9:26seconds before continuing, so if I open up
the console here.
9:34We can see what happens, so with request foo.com,
why this is happening, I can't do anything,
9:41right, even the run button hasn't finished
rerendering the fact that I clicked it.
9:45The browser is blocked, it's stuck, it can't
do anything until those requests complete.
9:51And then all hell breaks loose because I did
some stuff,it figured that out I'd done it,
9:56it couldn't actually render it.
9:59Couldn't do anything.
10:01That's because if that call stack has things
on it, and here it's got these yeah, it's
10:07still going.
10:08We've got the synchronous request, the browser
can't do anything else.
10:12It can't render, it can't run any other code,
it's stuck.
10:17Not ideal, right if we want people to have
nice fluid UIs, we can't block the stack.
10:22So, how do we handle this?
10:25Well the simplest solution we're provided
with is asynchronous callbacks, there's almost
10:29no blocking functions in the browser, equally
in node, they're all made asynchronous, which
10:37basically means we run some code, give it
a callback, and run that later, if you've
10:42seen JavaScript you've seen asynchronous callbacks,
what does this actually look like.
10:47Simple example to remind people where we're
at.
10:51Code like this, console.log hi.
10:54Write, we run the setTimeout, but that queue's
the console log for future so we skip on to
11:00JSConf and then five seconds later we log
"there" right, make sense?
11:07Happy.
11:08Basically that's setTimeout is doing something.
11:10So, asynchronous callbacks with regards to
the stacks we saw before ... how does this
11:15work?
11:17Let's run the code.
11:18Console.log hi.
11:21setTimeout.
11:23We know it doesn't run immediately, we know
it's going to run in five seconds time, we
11:28can't push it on to the stack, somehow it
just disappears, we don't have like a way
11:34of describing this yet, but we'll come to
it.
11:37We log JSConfEU, clear, five seconds later
somehow magically "there" appears on the stack.
11:45How does that happen?
11:49And that's ‑‑ this is basically where
the event loop comes in on concurrency.
11:54Right, so I've been kind of partially lying
do you and telling you that JavaScript can
11:59only do one thing at one time.
12:00That's true the JavaScript Runtime can only
do one thing at one time.
12:04It can't make an AJAX request while you're
doing other code.
12:06It can't do a setTimeout while you're doing
another code.
12:09The reason we can do things concurrently is
that the browser is more than just the Runtime.
12:15So, remember this diagram, the JavaScript
Runtime can do one thing at a time, but the
12:19browser gives us these other things, gives
us these we shall APIs, these are effectively
12:24threads, you can just make calls to, and those
pieces of the browser are aware of this concurrency
12:31kicks in.
12:33If you're back end person this diagram looks
basically identical for node, instead of web
12:38APIs we have C++ APIs and the threading is
being hidden from you by C++.
12:49Now we have this picture let's see how this
code runs in a more full picture of what a
12:54browser looks like.
12:55So, same as before, run code, console log
hi, logs hi to the console, simple.
13:02now we can see what happens when we call setTimeout.
13:05We are ‑‑ we pass this callback function
and a delay to the setTimeout call.
13:12Now setTimeout is an API provided to us by
the browser, it doesn't live in the V8 source,
13:17it's extra stuff we
get in that we're running the JavaScript run
13:23time in.
13:25The browser kicks off a timer for you.
13:28And now it's going to handle the count down
for you, right, so that means our setTimeout
13:33call, itself is now complete, so we can pop
off the stack.
13:37“JSConfEU”, clear, so, now we've got this
timer in the web API, which five seconds later
13:45is going to complete.
13:47Now the web API can't just start modifying
your code, it can't chuck stuff onto the stack
13:53when it's ready if it did it would appear
randomly in the middle of your code so this
13:58is where the task queue or callback queue
kicks in.
14:01Any of the web APIs pushes the callback on
to the task queue when it's done.
14:08Finally we get to the event loop, title of
the talk, what the heck is the event loop
14:13is like the simplest little piece in this
whole equation, and it has one very simple
14:19job.
14:20The event loops job is to look at the stack
and look at the task queue.
14:23If the stack is empty it takes the first thing
on the queue and pushes it on to the stack
14:27which effectively run it.
14:29So here we can see that now the stack is clear,
there's a callback on the task queue, the
14:34event loop runs, it says, oh, I get to do
something, pushes the callback on to the stack.
14:40Remember it's the stack is like JavaScript
land, back inside V8, the callback appears
14:45on the stack, run, console.log “there”,
and we're done.
14:50Does that make sense?
14:52Everyone where me?
14:54Awesome!
14:55Okay.
14:56So, now we can see how this works with probably
one of the first encounters you would have
15:00had with Async stuff which for some weird
reason someone says says you have to call
15:05setTimeout zero, ‑‑ okay, you want me
to run the function in zero time?
15:11Why would I wrap it in a setTimeout?
15:13Like the first time you run across this, if
you're like me,i see it doing something, but
15:17I don't know why.
15:20The reason is, generally, if you're trying
to defer something until the stack is clear.
15:26So we know looking at this, if you've written
JavaScript, that we're going to see the same
15:29result, we're going to see “hi” “JSConf”,
and “there” is going to appear at the
15:34end.
15:35We can see how that happens.
15:38The setTimeout zero, now it's going to complete
immediately and push it on to the queue, remember
15:44what I said about the event loop, it has to
wait till the stack is clear before it can
15:48push the callback on to the stack, so your
stack is going to continue to run, console.log
15:53“hi”, “JSConfEU” and clear, now the
event loop can kick in and call your callback.
16:01That's like an example of setTimeout zero,
is deferring that execution of code, for whatever
16:07reason to the end of the stack.
16:11Or until stack is clear.
16:13Okay.
16:15So, all these web APIs work the same way,
if we have AJAX request, we make an AJAX request
16:21to the URL with a callback, works the same
way, oops sorry, console log, “hi”, make
16:28an AJAX request, the code for running that
AJAX request does not live in JavaScript Runtime
16:33but in the browser as a web API, so we spin
it up with a callback in the URL, your code
16:40can continue to run.
16:42Until that XHR request completes, or it may
never complete, it's okay, the stack can continue
16:47to run, assuming it completes, gets pushed
to the queue,picked up by the event loop and
16:53it's run.
16:56That's all that happens when an Async call
happens.
16:58Let's do a crazy complicated example, I hope
this going to work, if you haven't realized
17:06all this is in keynote there's like I don't
know 500 animation steps in this whole deck.
17:12(code blows up, flames animation) (Applause)
J Whew ... no ... so ... interesting, we're
17:35given a link.
17:39Hmm ... is this big enough, can people see?
17:42Okay, so basically I wrote this talk for Scotland
JS, after the talk I broke half of the slides
17:52and could not be bothered to redo all the
slides because it was a total pain in the
17:56ass in keynote to do it so I took much easier
route (Laughing) of writing a tool that can
18:05visualize the JavaScript Runtime at Runtime,
and it's called loop.
18:11So, let's just run this example and, which
was kind of the example that we had on the
18:17previous slide, I haven't shimmed XHR yet,
it's doable I just haven't done it.
18:23As you can see the code, we're going to log
something, this is a shim around addEventListener,
18:31setTimeout and we're going to do a console.log. ‑‑
18:34I'm going to run it and see what happens so
... add a DOM API, add a timeout, code is
18:40going to continue to run, pushes the callback
into the queue which runs, and we're done.
18:49If I click on here then it's going to ... trigger
the web API, queue the callback for the click
18:55and run it.
18:56if I cluck a hundred times we can see what
happens.
18:59I clicked, the click doesn't get processed
immediately, itself gets pushed to the queue,
19:05as the queue gets processed, eventually my
click is going to get dealt with, right.
19:12So I have a few more examples I'm going to
run through here.
19:15Here we go, okay, so, I'm just going to run
through a few examples just to kind of talk
19:29about a few things that you might have run
in to and not thought about with Async APIs,
19:34In this example we call setTimeout four times
with the one second delay, and console.log
19:40“hi”.
19:43By the time the callbacks get queued... that
fourth callback we asked for a one second
19:52delay, and it's still waiting, the callback
hasn't run, right .
19:57this illustrates the ‑‑ like what time
out is actually doing, it's not a guaranteed
20:02time to execution, it's a minimum time to
execution, just like setTimeout zero doesn't
20:07run the code immediately it runs the code
next‑ish, sometime, right?
20:16So ... in this example I want to talk about
callbacks, so, depending on who, speak to
20:25and how they phrase things, callbacks can
be one of two things, callbacks can be any
20:29function that another function calls or callbacks
can be more explicitly an asynchronous callback
20:35as in one that will get pushed back on the
callback queue in the future.
20:39This bit of code illustrates the difference,
right.
20:43The forEach method on an array, it doesn't
run, it takes a function, which you could
20:48call a callback, but it's not running it asynchronously,
it's running it within the current stack.
20:56We could define an asynchronous forEach so
it can take an array, a callback and for each
21:02item in the array it's going to do a setTimeout
zero with that callback, I guess this should
21:08pass in the value, but any way, so, I'm going
to run it and we can see what the difference
21:14is, so for the first block of code that runs,
it's going to sit and block the stack, right?
21:21Until it's complete, whereas in the Async
version, okay, it's slowed down, but we're
21:26basically going to queue a bunch of callbacks
and they're going to clear and then we can
21:32actually run through and do a console.log.
21:35In this example the console.log is fast, so
the benefit of doing it asynchronously is
21:39not obviously but let's say you're doing some
slow processing on each element in the array.
21:49I think I have that shown somewhere no, no,
I don't.
21:55Okay.
21:56So let's say ‑‑ Ooops.
22:00So I have a delay function which is just slow,
it's just a slow thing.
22:07So ... let's say processing Async and here
processing Sync.
22:15Okay, now, I'm going to turn on a thing I've
literally hacked together this morning, which
22:24is to simulate the repaint or the render in
the browser, something I haven't touched on
22:28is how all of this interacts with rendering ‑‑
I've kind of touched on it but not really
22:35explained it.
22:36So, basically the browser is kind of constrained
by what you're doing javaScript, the browser
22:42would like to repaint the screen every 16.6
milliseconds, 60 frame a second is ideal,
22:48that's the fastest it will do repaints if
it can.
22:53But it's constrained by what you're doing
in JavaScript for various reasons, so it can't
22:58actually do a render if there is code on the
stack, right.
23:02Like the render kind of call is almost like
a callback in itself.
23:05It has to wait till the stack is clear.
23:07The difference is that the render is given
a higher priority than your callback, every
23:1416 milliseconds it's going to queue a rend,
wait till the stack is clear before it can
23:21actually do that render.
23:23So this is ‑‑ this render queue is just
simulating a render, every second it's can
23:28I do a render?
23:29Yes, can I do a render?
23:30Yes.
23:31Where, because our code isn't doing anything
now.
23:33If I run the code, you can see while we're
doing this slow synchronous loop through the
23:40array, our render is blocked, right, if our
render is blocked you can't select text on
23:44the screen, you can't click things and see
the response, right, like the example I showed
23:50earlier.
23:51In this example, okay, it's blocked while
we queue up the async time out, that relatively
23:57quick but we're given ‑‑ we're kind of
giving the render a chance between each element
24:04because we've queued it up asynchronously
to jump in there and do the render, does that
24:13make sense?
24:14>> Yeah
>> Yeah, cool.
24:15So, that's just kind of ‑‑ this is just
like a simulation of how the rendering works,
24:20but it just really shows you when people say
don't block the event loop, this is exactly
24:24what they're talking about.
24:25They're saying don't put shitty slow code
on the stack because when you do that the
24:28browser can't do what it needs to do, create
a nice fluid UI.
24:34This is why when you're doing things like
image processing or Animating too many things
24:38gets sluggish if you're not careful about
how you queue up that code.
24:44So an example of that, we can see with the
scroll handlers ‑‑ so scroll handle ‑‑
24:53like scroll events in the DOM trigger a lot,
right, they trigger like ‑‑ I presume
24:59they trigger on every frame like every 16
milliseconds, if I have code like this this
25:05right.
25:06On document.scroll, animate something, or
do some work.
25:11If I have this code, like as I scroll it's
going to queue up like a ton of callbacks
25:17right.
25:18And then it has to go through and process
all of those and each of the processing of
25:22those is slow, then, okay, you're not blocking
the stack, you're flooding the queue with
25:27queued events.
25:29So, this is like just helping visualize, I
guess, what happens when you actually trigger
25:36all these callbacks, there's way you can debounce
that to basically say okay, we're going to
25:42queue up all those events, but let's do the
slow work every few seconds or until the user
25:48stops scrolling for some amount of time I
think that's basically it.
25:58There's a whole other talk in how the hell
this works.
26:04Because basically in running the code, like
this code runs at Runtime, right, and it's
26:10slowed down by I run it through a Esprima
a JavaScript parser, I insert a big while
26:17loop, that takes half a second, it just slow
motions the code.
26:24Ship it to web worker and do a whole bunch
of stuff to visualize what's happening while
26:29doing it at run time that makes sense.
26:31A whole other talk in that.
26:33I'm super excited about it and will talk to
anyone about it after because I think it's
26:39kind of neat, so with that, thanks very much
( applause)