Computer Science

Javascript Event Loop

The JavaScript event loop is a mechanism that allows JavaScript to handle multiple events and tasks simultaneously. It works by continuously checking the call stack and the message queue, and executing tasks in the queue when the call stack is empty. This allows for non-blocking asynchronous programming in JavaScript.

Written by Perlego with AI-assistance

8 Key excerpts on "Javascript Event Loop"

  • Book cover image for: Advanced JavaScript
    No longer available |Learn more

    Advanced JavaScript

    Speed up web development with the powerful features and benefits of JavaScript

    Unlike most programming languages, JavaScript is an asynchronous programming language. More specifically, it is a single threaded, event driven, asynchronous programming language. This means that JavaScript does not idle when waiting for the results of a long-running operation. It runs other code blocks while waiting. JavaScript manages this with the Event Loop. The event loop is composed of four parts, a function stack, a memory heap, an event queue, and the event loop. These four parts work together to handle events fired from operation completion.

    Exercise 16: Handling the Stack with an Event Loop

    To better understand why events in your program are being fired and handled in the expected order, look at the program provided next, and without running the program, write out the expected output of the program.
    For the first 10 steps of the program, write the expected stack, queue, and heap at each step. A step is any time an event fires, the event loop dequeues an event, or the JS Engine handles a function call:
    step 0 stack: <global> queue: <empty> heap: <empty> Snippet 2.5: Call stack example code (starting step) The program is displayed in the following snippet: function f1() { console.log( 'f1' ); } function f2() { console.log( 'f2' ); } function f3() {   console.log( 'f3' );   setTimeout( f5, 90 ); } function f4() { console.log( 'f4' ); } function f5() { console.log( 'f5' ); } setTimeout( f1, 105 ); setTimeout( f2, 15 ); setTimeout( f3, 10 ); setTimeout( f4, 100 ); Snippet 2.6: Call stack example code (program) To demonstrate a simplified form of how the Event Loop handles the stack, queue, and heap while handling JavaScript events, perform the following steps:
    1. Add an event loop stack frame to the stack if a function is called and being handled.Process the function and add the necessary event and handler info to the heap. Remove the event and handler in the next step.
  • Book cover image for: JavaScript Concurrency
    In a concurrency context, we're mostly interested in the mechanics that tie all these platform pieces together. Our application is written mainly in JavaScript, and the interpreter knows how to parse and run it. But, how does this ultimately translate into visual changes on the page? How does the networking component of the browser know to make an HTTP request, and how does it invoke the JavaScript interpreter once the response has arrived?
    It's the coordination of these moving parts that restricts our concurrency options in JavaScript. These restrictions are necessary, because without them, programming web applications would become too complex.

    Event loops

    Once an execution environment is in place, the event loop is one of the first components to start. Its job is to service one or more task queues in the environment. Browser vendors are free to implement queues as they see fit, but there has to be at least one queue. Browsers can place every task in one queue if they please, and treat every task with equal priority. The problem with doing so would mean that if the queue is getting backlogged, tasks that must receive priority, such as mouse or keyboard events, are stuck in line.
    In practice, it makes sense to have a handful of queues, if for no other reason than to separate tasks by priority. This is all the more important because there's only one thread of control—meaning only one CPU—that will process these queues. Here's what an event loop that services several queues by varying levels of priorities looks like:
    Even though the event loop is started along with the execution environment, this doesn't mean that there's always tasks for it to consume. If there were always tasks to process, there would never be any CPU time for the actual application. The event loop will sit and wait for more tasks, and the queue with the highest priority gets serviced first. For example, with the queues used in the preceding image, the interactive queue will always be serviced first. Even if the event loop is making its way through the render queue tasks, if an interactive
  • Book cover image for: Mastering Node.js - Second Edition
    • Sandro Pasquali, Kevin Faaborg, Glenn Geenen(Authors)
    • 2017(Publication Date)
    • Packt Publishing
      (Publisher)
    synchronously . Now, let's dive deeper into how Node's event loop works.
    Passage contains an image

    Understanding the event loop

    The following three points are important to remember, as we break down the event loop:
    • The event loop runs in the same (single) thread your JavaScript code runs in. Blocking the event loop means blocking the entire thread.
    • You don't start and/or stop the event loop. The event loop starts as soon as a process starts, and ends when no further callbacks remain to be performed. The event loop may, therefore, run forever.
    • The event loop delegates many I/O operations to libuv, which manages these operations (using the power of the OS itself, such as thread pools), notifying the event loop when results are available. An easy-to-reason-about single-threaded programming model is reinforced with the efficiency of multithreading.
    For example, the following while loop will never terminate: let stop = false;setTimeout(() => { stop = true;}, 1000);while (stop === false) {};
    Even though one might expect, in approximately one second, the assignment of a Boolean true to the variable stop, tripping the while conditional and interrupting its loop; this will never happen. Why? This while loop starves the event loop by running infinitely, greedily checking and rechecking a value that is never given a chance to change, as the event loop is never given a chance to schedule our timer callback for execution. This proves the event loop (which manages timers), and runs on the same thread.
    According to the Node documentation, "The event loop is what allows Node.js to perform non-blocking I/O operations — despite the fact that JavaScript is single-threaded — by offloading operations to the system kernel whenever possible."
    The key design choice made by Node's designers was the implementation of an event loop as a concurrency manager. For example, notifying your Node-based HTTP server of network connections to your local hardware is handled by the OS passing along, via libuv, network interface events.
  • Book cover image for: Ultimate Node.js for Cross-Platform App Development
    eBook - ePub

    Ultimate Node.js for Cross-Platform App Development

    Learn to Build Robust, Scalable, and Performant Server-Side JavaScript Applications with Node.js

    This diagram represents how the Node.js application works behind the scenes. The V8 engine compiles the code you write in your program, and the application code uses binding to communicate with low-level Node.js components. After events are fired from the application code, they are pushed into the event queue in the order in which they were originally fired from the application. The event loop processes all the events, calls their callback functions, and sends them to worker threads for processing until the event queue becomes empty. After the callback function executes, its callback is returned to the event queue, waiting for the event loop to pick it up.
    Part of your confusion may stem from the choice of technical terms used in the second diagram. If you look closely, under “NODE.JS BINDINGS”, it says “(NODE API)”, which unfortunately are two different things. The Node.js API is the user interface for its built-in libraries, while bindings, from a software programming perspective, are bridges between code written in different languages.
    A client interacts with a web application by sending requests to a web server, which can be non-blocking or blocking. These requests are as follows:
    • Query data
    • Deletion of data
    • Update data
    Node.js takes incoming requests and adds them to an event queue. Requests are then routed through the event loop, one at a time. Make sure your requirements are simple enough to not require external resources. The event loop handles simple requests (non-blocking operations), such as I/O polling, and returns responses to the appropriate clients.
    One thread in the thread pool is assigned to one complex request. This thread is responsible for accessing external resources, completing specific lock requests, and managing computing power, databases, file systems, and more.
    When the task is completed, the response is sent to the event loop and then returned to the client. The following are the core components that make the Node.js framework incredible:
    • V8:
  • Book cover image for: Learn ECMAScript
    No longer available |Learn more
    • Narayan Prusty, MEHUL MOHAN(Authors)
    • 2018(Publication Date)
    • Packt Publishing
      (Publisher)
    The main thread also maintains a queue, which has asynchronous tasks queued to be executed one by one. These queued tasks can be event handlers, callbacks, or any other kind of task. New tasks are added to the queue as AJAX requests/responses happen, events occur, timers are registered, and more. One long-running queue task can stop the execution of all other queue tasks and the main script. The main thread executes the tasks in this queue whenever possible.
    HTML5 introduced web workers, which are actual threads running parallel to the main thread. When a web worker finishes executing or needs to notify the main thread, it simply adds a new event item to the queue. 
    We'll discuss web workers separately in Chapter 9 , JavaScript on the Web .
    Passage contains an image

    The event loop

    JavaScript follows an event loop-based model in how it works. This is very different from languages such as Java. Although modern JavaScript compilers implement a very complex and heavily optimized version of the event loop model, we can still basically understand how the event loop works.
    Passage contains an image

    The call stack

    JavaScript is a single-threaded language. That means it can have one call stack at a given time (take one thread = one call stack). Furthermore, it implies that JavaScript cannot do more than two things at a time. Or can it?
    When you call a function, you step inside that function. This function is added to the call stack. When the function returns a value, the function is popped from the call stack. Let's take a look at this example:
    const page1 = $.syncHTTP('http://example.com/page1');const page2 = $.syncHTTP('http://example.com/page2');const page3 = $.syncHTTP('http://example.com/page3');const page4 = $.syncHTTP('http://example.com/page4');console.log(page1, page2, page3, page4);
    For the sake of simplicity, consider $.syncHTTP as a predefined method that performs synchronous
  • Book cover image for: The TypeScript Workshop
    eBook - ePub

    The TypeScript Workshop

    A practical guide to confident, effective TypeScript programming

    • Ben Grynhaus, Jordan Hudgens, Rayon Hunte, Matt Morgan, Wekoslav Stefanovski(Authors)
    • 2021(Publication Date)
    • Packt Publishing
      (Publisher)

    10. Event Loop and Asynchronous Behavior

    Overview
    In this chapter, you'll investigate how a web page actually works within the browser, with a special focus on how, when, and why the browser executes the JavaScript code we provide. You'll dive deep into the intricacies of the event loop and see how we can manage it. Lastly, you'll learn about the tools that TypeScript offers you. By the end of this chapter, you will be able to better manage the asynchronous nature of the execution.

    Introduction

    In the previous chapter, you learned the fundamentals of generics and conditional types. This chapter introduces you to event loops and asynchronous behavior. However, before you proceed with learning these topics, let's have a look at a hypothetical scenario to really understand how synchronous and asynchronous executions work.
    Imagine a small bank that has a single teller. His name is Tom, and he's serving clients all day. Since it's a small bank and there are few clients, there's no queue. So, when a client comes in, they get Tom's undivided attention. The client provides all the necessary paperwork, and Tom processes it. If the process needs some kind of outside input, such as from a credit bureau or the bank's back-office department, Tom submits the request, and he and the client wait for the response together. They might chat a bit, and when the response comes, Tom resumes his work. If a document needs to be printed, Tom sends it to the printer that's right on his desk, and they wait and chat. When the printing is done, Tom resumes his work. Once the work is completed, the bank has another satisfied client, and Tom continues with his day. If somebody comes while Tom is serving a client (which happens seldom), they wait until Tom is completely done with the previous client, and only then do they begin their process. Even if Tom is waiting on an external response, the other client will have to wait their turn, while Tom idly chats with the current client.
  • Book cover image for: JavaScript Unlocked
    No longer available |Learn more
    http://www.creativebloq.com/web-design/responsive-web-design-tips-bbc-news-9134667 ). We extract the components of an application required for core experience and load them first. Then, progressively we add an enhanced experience. As for JavaScript, what we have to care the most about are nonblocking flows. Thus, we have to avoid loading scripts synchronously prior to HTML rendering, and we have to wrap all long-running tasks into asynchronous callbacks. This is something that you most probably already know. But do you do it efficiently?
    In this chapter, we will cover the following topics:
    • Nonblocking JavaScript
    • Error-first callback
    • The continuation-passing style
    • Handling asynchronous functions in the ES7 way
    • Parallel tasks and task series with the Async.js library
    • Event handling optimization

    Nonblocking JavaScript

    First of all, let's look at what really happens when we do things asynchronously. Whenever we invoke a function in JavaScript, it creates a new stack frame (execution object). Every inner call gets into this frame. Here the frames are pushed and popped from the top of the call stack in the LIFO (last in, first out ) manner. In other words, in the code, we call the foo function and then the bar function; however, during execution, foo calls the baz function. In this case, in the call stack, we have the following sequence: foo , baz , and only then bar . So bar is called after the stack frame of foo is empty. If any of the functions perform a CPU-intensive task, all the successive calls wait for it to finish. However, JavaScript engines have Event Queues (or task queues).
    If we subscribe a function to a DOM event or pass a callback to a timer (setTimeout or setInterval ) or through any Web I/O APIs (XHR, IndexedDB, and FileSystem), it ends up in a corresponding queue. Then, the browser's event loop decides when and which callback to push in the callback stack. Here is an example:
    function foo(){ console.log( "Calling Foo" ); } function bar(){ console.log( "Calling Bar" ); } setTimeout(foo, 0 ); bar();
    Using setTimeout( foo, 0 ) , we state that foo shall be called immediately, and then we call bar . However, foo
  • Book cover image for: The JavaScript Workshop
    No longer available |Learn more

    The JavaScript Workshop

    A New, Interactive Approach to Learning JavaScript

    • Joseph Labrecque, Jahred Love, Daniel Rosenbaum, Nick Turner, Gaurav Mehla, Alonzo L. Hosford, Florian Sloot, Philip Kirkbride(Authors)
    • 2019(Publication Date)
    • Packt Publishing
      (Publisher)
    An alternative is to make the function conditional by requiring it to execute only when enough time has passed since its last execution. This is the essential basis of a timer event. Unlike C, JavaScript is a single-threaded platform, meaning it can only execute a single thread throughout your entire application. A thread is an execution space in the CPU. If you have one thread, then only a single series of function executions can occur at once. In JavaScript, this does not mean the underlying engine doesn't use, or have access to, more than one thread; only that your application has programmatic access to one single thread. Since JavaScript runs within an engine, known as a virtual machine, it is driven by a number of rules that determine how your code is run. The JavaScript virtual machine follows an architecture known as an event loop. This means that the loop in the preceding C example is already occurring within the JavaScript engine that your application runs within. However, within that loop, the JavaScript engine manages code execution for each of the function calls your application makes, among other things, regardless of whether those calls invoke your own functions or those native to JavaScript. Exercise 6.01: Custom Timer As we mentioned previously, many developers coming from lower-level languages will consider a loop as a means to create timed function invocations. If a loop can occur indefinitely, then we only need to check the current system time and invoke functions when sufficient time has passed. For instance, when animating, in order to control the speed of the animation, you may want to ensure your frame update functions are executed with a sufficient period of time between each invocation. Without this control, your animation frames will update with every possible cycle of the JavaScript runtime, which may be very fast on some machines, while not so fast on weaker machines. In this exercise, you will implement one such loop
Index pages curate the most relevant extracts from our library of academic textbooks. They’ve been created using an in-house natural language model (NLM), each adding context and meaning to key research topics.