Chapter 13: Chapter 13. Surviving events
The chapter introduction recalls a simplified event-loop model and defines timers as asynchronous delays before previewing the chapter’s topics.
After this chapter you will be able to
- Simplified event queue model. Explain that JavaScript’s single-threaded execution model was introduced with an event loop and a queue where events wait to be processed, and that this is only a simplified picture of browser behavior.
- Macrotask and microtask roles. Distinguish macrotasks from microtasks using the section’s examples and explain why microtasks run before rendering.
- Event loop iteration order. Trace a single event-loop iteration from the macrotask check through microtask processing, the rendering decision, and the return to the start.
- Task duration and responsiveness. Explain how task duration affects rendering and why frequent, expensive event handlers can make a page feel slow.
- Queued clicks and execution. Explain why clicking a button while mainline JavaScript is running does not immediately invoke its handler, and how the click can still enter the task queue.
- Two click task timeline. Trace the mainline task and two click handlers through the example, including what the event loop does between tasks when the microtask queue is empty.
- Asynchronous promise handler scheduling. Explain why the handler attached to the already resolved promise does not run immediately, and describe how it becomes a microtask after the first click handler finishes.
- Microtask priority over click tasks. Trace why the promise handler runs before the second button’s click handler, even though the second click task was queued earlier.
- Rendering after microtask completion. Explain when the browser can render in this example and how additional microtasks queued by a promise handler affect that opportunity.
- Minimum Timer Delay. Explain that a timer delays code execution by at least a specified number of milliseconds, but does not guarantee that the code will run at that exact time.
- Timer Creation And Cancellation. Distinguish timers that fire once from timers that fire periodically, and name the methods used to create and clear them. Describe these methods as host-environment facilities, exposed by the browser on the global window object.
- Timer delays and task execution. Explain that a timer delay determines when its task can be added to the queue, not when its handler will execute. Trace why the example’s 10 ms time-out does not begin until 28 ms.
- Queued interval invocation limits. Describe what happens when an interval fires while an invocation of that same interval is already waiting in the task queue, and distinguish that from firing while its handler is executing.
- Intervals versus repeated time-outs. Distinguish an interval from a time-out that schedules another time-out after each callback, including how much time may pass between callback executions.
- Long tasks and responsiveness. Explain why a long-running JavaScript operation can make the browser appear to hang, even when the operation is producing page content.
- Timer-scheduled work chunks. Describe how the section breaks an expensive operation into smaller timer-scheduled parts and keeps track of progress until the work is done.
- Event handler registration and data. Describe how addEventListener registers a handler and what the browser passes to that handler when the event occurs.
- Event target and handler context. Distinguish the event object’s target from this inside an event handler, including why they are often—but not always—the same element.
- Capturing and bubbling order. Trace how a click travels down to its target during capturing and back up during bubbling. Explain how the third argument to addEventListener selects a handler’s phase and determines the order in which handlers run.
- Handler element versus event target. Distinguish the element whose handler is running from the element where the click occurred, using this and event.target in the nested-container example.
- Delegating clicks to an ancestor. Explain how one handler on a table can handle clicks on its cells through bubbling and event.target, instead of registering the same handler on every cell. State why the delegated handler must be attached to an ancestor of the targets.
- Loose coupling through custom events. Explain why custom events are preferable to a required global function when shared code needs to notify page code of a condition.
- Ajax custom event example. Trace how the example uses application-specific events to separate a simulated Ajax operation from the page’s pinwheel display.
What it builds on
- Event-handling overview (chapter 2) · Introduces the earlier event-handling overview.
- Registering event handlers (chapter 2) · Assumes that click handlers can be registered for buttons.
- Diving into promises (chapter 6) · The earlier explanation of promises and their handlers.
- The this parameter: introducing the function context (chapter 4) · Earlier introduction to this as a function context.
Section by section
Introduction
The chapter introduction recalls a simplified event-loop model and defines timers as asynchronous delays before previewing the chapter’s topics.
- Simplified event queue model: Explain that JavaScript’s single-threaded execution model was introduced with an event loop and a queue where events wait to be processed, and that this is only a simplified picture of browser behavior.
Why it matters: It gives you a starting point for understanding execution order without mistaking that starting point for the whole story. - Asynchronous timer delay: Describe a timer as a JavaScript feature that delays execution of code asynchronously by a specified amount of time.
Why it matters: This basic role of timers sets up the later discussion of their effect on application responsiveness.
Key terms: single-threaded execution model, event loop, event queue, timers, asynchronously
13.1 Diving into the event loop
This section explains the event loop’s macrotask and microtask queues, how one iteration processes tasks and rendering, and why lengthy tasks can make a page unresponsive.
- Macrotask and microtask roles: Distinguish macrotasks from microtasks using the section’s examples and explain why microtasks run before rendering.
Why it matters: The distinction explains why some asynchronous updates happen before the page is drawn. - Event loop iteration order: Trace a single event-loop iteration from the macrotask check through microtask processing, the rendering decision, and the return to the start.
Why it matters: This order lets you reason about which work finishes before the next possible screen update. - Serial execution and separate queuing: Explain how tasks can be queued while JavaScript runs even though task execution is single-threaded and tasks do not interrupt one another.
Why it matters: A new event can wait its turn without interrupting code that is already running. - Task duration and responsiveness: Explain how task duration affects rendering and why frequent, expensive event handlers can make a page feel slow.
Why it matters: It connects event-loop scheduling to the responsiveness people actually experience.
Key terms: macrotasks, microtasks, promise callbacks, application state, event loop, iteration, macrotask queue, microtask queue, Update rendering, task queues
13.1 Do you know?
This section poses questions to check the reader’s understanding of timer timing, interval callbacks, and event-handler context.
13.1.1 An example with only macrotasks
A two-click example shows how single-threaded JavaScript queues events and runs their handlers in successive event-loop iterations.
- Queued clicks and execution: Explain why clicking a button while mainline JavaScript is running does not immediately invoke its handler, and how the click can still enter the task queue.
Why it matters: This explains why an event can occur well before its handler runs. - Two click task timeline: Trace the mainline task and two click handlers through the example, including what the event loop does between tasks when the microtask queue is empty.
Why it matters: The timeline makes the difference between when a click occurs and when its handler runs concrete.
Key terms: single-threaded execution model, task queue, click event, event loop, mainline JavaScript code, firstHandler, secondHandler, microtask queue, UI
13.1.2 An example with both macro- and microtasks
This section uses a resolved promise inside a click handler to show how the event loop prioritizes microtasks over queued click tasks and rendering.
- Asynchronous promise handler scheduling: Explain why the handler attached to the already resolved promise does not run immediately, and describe how it becomes a microtask after the first click handler finishes.
Why it matters: A resolved promise does not make its handler interrupt the code that is running. - Microtask priority over click tasks: Trace why the promise handler runs before the second button’s click handler, even though the second click task was queued earlier.
Why it matters: Queue arrival time alone cannot tell you which callback will run next. - Rendering after microtask completion: Explain when the browser can render in this example and how additional microtasks queued by a promise handler affect that opportunity.
Why it matters: A chain of microtasks can delay both a visible page update and the next click handler.
Key terms: promise handlers, already resolved promise, microtask, microtask queue, event loop, macrotask, task queue, re-render, promise success microtask
13.2 Taming timers: time-outs and intervals
This section introduces what timers do, the browser methods for creating and clearing them, and why delayed execution can help keep a page responsive.
- Minimum Timer Delay: Explain that a timer delays code execution by at least a specified number of milliseconds, but does not guarantee that the code will run at that exact time.
Why it matters: Thinking of a timer as an exact appointment can lead to incorrect expectations about when code runs. - Timer Creation And Cancellation: Distinguish timers that fire once from timers that fire periodically, and name the methods used to create and clear them. Describe these methods as host-environment facilities, exposed by the browser on the global window object.
Why it matters: These distinctions let you choose and clear the kind of timer your code needs. - Responsive Long Task Motivation: Explain why delaying pieces of a long-running task can help keep a web application responsive, without describing the later implementation.
Why it matters: It connects timer use to a visible problem: a page becoming slow or unresponsive.
Key terms: timer, delay, setTimeout, setInterval, clearTimeout, clearInterval, window, host environment, long-running tasks, event loop
13.2.1 Timer execution within the event loop
This section uses a timing example to show why timer callbacks may run later than their stated delays and why intervals behave differently from repeatedly scheduled time-outs.
- Timer delays and task execution: Explain that a timer delay determines when its task can be added to the queue, not when its handler will execute. Trace why the example’s 10 ms time-out does not begin until 28 ms.
Why it matters: It keeps you from relying on a timer callback to run at an exact moment. - Queued interval invocation limits: Describe what happens when an interval fires while an invocation of that same interval is already waiting in the task queue, and distinguish that from firing while its handler is executing.
Why it matters: It explains why an interval can miss firings yet still have callbacks run close together. - Intervals versus repeated time-outs: Distinguish an interval from a time-out that schedules another time-out after each callback, including how much time may pass between callback executions.
Why it matters: The choice between these timer patterns changes whether callbacks may occur back-to-back.
Key terms: timer task, task queue, setTimeout(fn, delay), event loop, setInterval, interval task, setTimeout, callback, delay
13.2.2 Dealing with computationally expensive processing
The section shows how to keep a browser responsive during expensive JavaScript work by splitting it into timer-scheduled chunks.
- Long tasks and responsiveness: Explain why a long-running JavaScript operation can make the browser appear to hang, even when the operation is producing page content.
Why it matters: It explains why finishing a large operation in one uninterrupted run can be a poor experience for the user. - Timer-scheduled work chunks: Describe how the section breaks an expensive operation into smaller timer-scheduled parts and keeps track of progress until the work is done.
Why it matters: Chunking lets substantial work continue without occupying the browser for one long stretch. - Zero-delay timer rendering: Distinguish what a zero-delay timer requests from an immediate callback, and describe the visible effect of allowing rendering between chunks.
Why it matters: The chance to render between chunks is what makes the timer approach feel more responsive.
Key terms: single-threaded, rendering, unresponsive, timers, chunkSize, iteration, nonblocking operations, time-out delay, callback, microtasks
13.3 Working with events
This section explains how a registered event handler receives event information and distinguishes the event’s target from the element on which the handler was registered.
- Event handler registration and data: Describe how addEventListener registers a handler and what the browser passes to that handler when the event occurs.
Why it matters: It connects an event occurring in the browser to the code that responds to it. - Event target and handler context: Distinguish the event object’s target from this inside an event handler, including why they are often—but not always—the same element.
Why it matters: It prevents you from treating the event’s origin and the handler’s registered element as interchangeable.
Key terms: addEventListener, event handler, event object, target, this
13.3.1 Propagating events through the DOM
This section explains how clicks travel through the DOM, how handlers identify the clicked element, and how an ancestor can handle clicks for its descendants.
- Capturing and bubbling order: Trace how a click travels down to its target during capturing and back up during bubbling. Explain how the third argument to addEventListener selects a handler’s phase and determines the order in which handlers run.
Why it matters: Propagation and handler phase explain why nested elements’ click handlers run in a particular order. - Handler element versus event target: Distinguish the element whose handler is running from the element where the click occurred, using this and event.target in the nested-container example.
Why it matters: An ancestor’s handler needs to tell its own element apart from the element the user actually clicked. - Delegating clicks to an ancestor: Explain how one handler on a table can handle clicks on its cells through bubbling and event.target, instead of registering the same handler on every cell. State why the delegated handler must be attached to an ancestor of the targets.
Why it matters: Delegation lets one table handler do the work of many identical cell handlers.
Key terms: event capturing, event bubbling, capturing phase, bubbling phase, addEventListener, this, event.target, event handler, event target, event delegation
13.3.2 Custom events
The section shows how custom events let shared code signal application-specific conditions without depending on the page code that reacts to them.
- Loose coupling through custom events: Explain why custom events are preferable to a required global function when shared code needs to notify page code of a condition.
Why it matters: Independent event handlers make shared code easier to reuse without tying it to each page’s reactions. - Ajax custom event example: Trace how the example uses application-specific events to separate a simulated Ajax operation from the page’s pinwheel display.
Why it matters: The example makes the separation concrete: the Ajax code reports progress, and the page chooses how to display it.
Key terms: custom events, loose coupling, close coupling, event handlers, ajax-start, ajax-complete, url property, time-out, pinwheel
13.4 Summary
13.5 Exercises
Where this is used later
- Untestable browser issues (chapter 14) · Working with browser events and their handlers
Concepts explained in this chapter
- event queueA queue that holds pending events for later processing.
- event loopA runtime scheduling mechanism that coordinates when queued events and callbacks are handled by an application.
- taskA unit of scheduled work processed by a runtime's event loop, such as an event handler or timer callback.
- macrotaskAn event-loop task such as an event handler or timer callback, processed separately from microtasks.
- microtaskA unit of deferred work processed after the current task and before the event loop proceeds to another task.
- event bubblingThe phase of event dispatch in which an event travels from its target up through the DOM hierarchy.
- event capturingThe phase of DOM event dispatch in which an event travels down the hierarchy toward its target.
- event delegationAn event-handling pattern in which a parent or ancestor element handles events for descendant elements by relying on propagation.
- custom eventA programmer-defined event that represents an application-specific occurrence and can be triggered and handled like a built-in event.
- setIntervalA timer function that repeatedly schedules a callback at a specified interval until canceled.
- setTimeoutA timer function that schedules a callback to run after a specified delay.
- timer delayThe minimum elapsed time requested before a timer's corresponding task is added to the task queue, not a guarantee of when it executes.
- event propagationEvent propagation is the movement of an event through the DOM hierarchy from its target toward or from ancestor elements.
- decouplingA design property in which interacting components know little or nothing about one another's internal details or control flow.
- microtask queueA queue that holds microtasks to be processed between event-loop tasks.
- non-blocking callAn operation arranged so that its work does not block the program’s execution while it is being performed.
- timerA host-environment scheduling mechanism for running code after a delay or at repeated intervals.
- macrotask queueA queue that holds pending tasks for processing by an event loop.
- handlerA callable routine that runs in response to a dispatched event.
- browser rendering pipelineThe browser process of producing or updating a web page’s visual presentation from its document and styles.
- event targetThe object or element on which an event originally occurred and which is exposed through the event object's target reference.
- single-threaded execution modelAn execution model in which only one unit of code runs at a time within a given execution context.
These guides are generated from the text of Manning books by Manning's knowledge graph and link to the sections they draw on. The full books are available on liveBook and at manning.com.
