Skip to content
← back to home

What the heck is the event loop anyway? | Philip Roberts | JSConf EU

JSConf

youtube· 26:38standard

1.Introduction to the Event Loop

0:00 / 0:31

The speaker introduces himself and the topic of the event loop in JavaScript. He shares his personal journey of understanding how JavaScript actually works, despite being a professional developer.

  • Event Loop
  • JavaScript Runtime

What's inside this course

  1. 0:00

    1. Introduction to the Event Loop

    The speaker introduces himself and the topic of the event loop in JavaScript. He shares his personal journey of understanding how JavaScript actually works, despite being a professional developer.

  2. 0:31

    2. Initial Confusion and Research

    The speaker recounts his initial confusion about JavaScript's internal workings, encountering terms like V8, single-threaded, call stack, event loop, and callback queue without fully grasping their meaning. He highlights the common misconception that V8 handles all asynchronous operations.

  3. 1:52

    3. Simplified JavaScript Runtime View

    The speaker presents a simplified view of the JavaScript runtime, focusing on the heap and call stack. He then reveals that common asynchronous functions like setTimeout or DOM manipulation are not part of V8, hinting at a larger ecosystem.

  4. 4:00

    4. The Bigger Picture: Web APIs and Event Loop

    The speaker introduces the complete picture of the JavaScript runtime environment, including Web APIs provided by the browser and the crucial roles of the event loop and callback queue. This expanded view explains how JavaScript handles asynchronous operations.

  5. 6:39

    5. JavaScript's Single-Threaded Nature

    The speaker reiterates that JavaScript is a single-threaded language with a single call stack, meaning it can only execute one piece of code at a time. He visualizes this concept with a simple code example involving function calls and returns.

  6. 8:17

    6. Visualizing the Call Stack

    Through a detailed animation, the speaker demonstrates how functions are pushed onto and popped off the call stack during execution. This visualization clarifies the concept of the call stack as a record of the program's current position.

  7. 10:04

    7. Call Stack in Practice: Errors and Stack Overflow

    The speaker connects the theoretical concept of the call stack to practical scenarios like error stack traces and 'blowing the stack' (stack overflow). He shows how these common development issues are direct consequences of call stack behavior.

  8. 11:59

    8. The Problem of Blocking Operations

    The speaker addresses the critical issue of 'blocking' in single-threaded JavaScript, explaining that slow operations like network requests or long loops can halt program execution. He illustrates this with a synchronous AJAX request example.

  9. 14:03

    9. Blocking the Browser UI

    Using a live demonstration, the speaker shows the real-world impact of blocking operations on a browser's user interface. He illustrates how synchronous code can freeze the UI, preventing user interaction and rendering updates, leading to a poor user experience.

  10. 17:02

    10. Introducing Asynchronous Callbacks

    The speaker introduces asynchronous callbacks as the primary solution to blocking issues in JavaScript. He explains that these functions are executed later, allowing the main thread to continue, and demonstrates this with a setTimeout example.

  11. 19:09

    11. Concurrency and the Browser Environment

    The speaker clarifies that while the JavaScript runtime is single-threaded, concurrency is achieved through the browser environment. Web APIs (or C++ APIs in Node.js) handle long-running tasks in separate threads, allowing JavaScript to remain non-blocking.

  12. 20:49

    12. How setTimeout Works with Web APIs and Task Queue

    The speaker provides a detailed explanation of how setTimeout functions within the browser environment. He shows how the browser's Web API handles the timer, and once complete, pushes the callback function onto the task queue.

  13. 23:21

    13. The Event Loop's Simple Job

    The speaker finally explains the core function of the event loop: it continuously checks if the call stack is empty and, if so, moves the first callback from the task queue onto the stack for execution. This simple mechanism enables non-blocking behavior.

  14. 25:00

    14. Understanding setTimeout(0)

    The speaker demystifies the common practice of using setTimeout(0). He explains that it doesn't execute immediately but defers the callback until the current call stack is completely clear, making it useful for ensuring code runs after other synchronous operations.

Every chapter ends with a checkpoint (quiz, flashcards, retell, diagram, or prediction) and the course closes with a final boss-fight. More courses →

Full transcript of “What the heck is the event loop anyway? | Philip Roberts | JSConf EU

336 segments
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)