JavaScript
Completed
-
Section 1: Getting Started
-
Section 2: Core Syntax and Types
-
Section 3: Strings and Numbers in Depth
-
Section 4: Control Flow
-
Section 5: Functions
-
Section 6: Objects and Arrays
-
Section 7: Maps, Sets, and Symbols
-
Section 8: Asynchronous JavaScript
-
Section 9: Object-Oriented and Prototypes
-
Section 10: The DOM
-
Section 11: Browser APIs
-
Section 12: Modern JavaScript (ES2015-ES2025)
-
Section 13: Functional Programming Patterns
-
Section 14: Error Handling and Debugging
-
Section 15: Testing
-
Section 16: Accessibility for JavaScript Developers
-
Section 17: Internationalization and Localization
-
Section 18: Performance
-
Section 19: Node.js Fundamentals
-
Section 20: Regular Expressions
-
Section 21: Design Patterns in JavaScript
-
Section 22: Security Basics
-
Section 23: Data Structures and Algorithms in JavaScript
-
Section 24: Practical Projects
-
Section 25: More Advanced Async Patterns
-
Section 26: More Object and Class Practice
-
Section 27: Working with Dates and Internationalization
-
Section 28: Web Components
-
Section 29: More DOM and Browser Practice
-
Section 30: Build Tooling for Vanilla JavaScript
-
Section 31: More Practice Projects
-
Section 32: Interview and Algorithm Practice
-
Section 33: Error Objects (MDN Reference)
-
Section 34: TypedArrays and Binary Data
-
Section 35: Reflection and Metaprogramming (MDN Reference)
-
Section 36: More Global Functions (MDN Reference)
214: The Page Visibility API
I once worked with a junior dev who spent an entire weekend trying to figure out why our staging server was crashing every Tuesday morning. He’d written a really slick real-time dashboard that polled an API every three seconds to update a set of stock tickers. It worked perfectly during his tests. But as it turns out, a few of our internal testers had the dashboard open in a background tab for eight hours a day. Even though they weren't looking at the page, the browser kept firing those requests. We essentially DDOSed our own server because the app didn't know it was invisible.
That's where the Page Visibility API comes in. It’s a small but powerful tool that tells your code whether the user is actually looking at your page or if they've switched tabs, minimized the window, or locked their screen. Instead of blindly running heavy processes, you can actually be a "good citizen" of the browser and the network.
Tracking the Visibility State
The core of this API is the document.visibilityState property. It doesn't just return a boolean; it gives you a string. Most of the time, you're looking for 'visible' or 'hidden'. While there used to be a document.hidden property, it's largely been superseded by the more descriptive state string.
The real magic, however, happens when you listen for the visibilitychange event. This event fires every time the state flips. I usually set this up as a global listener early in the application lifecycle so I can toggle global flags for things like animations or API polling.
document.addEventListener('visibilitychange', () => {
if (document.visibilityState === 'hidden') {
console.log('Tab is out of sight. Time to relax.');
// Stop the heavy lifting here
} else {
console.log('Welcome back! Resuming work.');
// Kick things back into gear
}
});
Optimizing Resource Consumption
You might be wondering, "Doesn't the browser already throttle timers in background tabs?" It does, but it's inconsistent across different browsers and OS power-saving modes. Relying on the browser's default throttling is a gamble; using the Visibility API is a strategy.
I typically use this for three specific things: pausing requestAnimationFrame loops to save GPU/CPU, stopping setInterval polls to save server bandwidth, and pausing video or audio playback if the UX demands it. For example, if you're building a chat app, you might stop polling for new messages and instead switch to a "catch-up" fetch the moment the user returns to the tab.
let pollInterval;
function startPolling() {
pollInterval = setInterval(async () => {
const data = await fetch('/api/updates');
console.log('Updating UI with new data...');
}, 5000);
}
function stopPolling() {
clearInterval(pollInterval);
}
document.addEventListener('visibilitychange', () => {
document.visibilityState === 'visible' ? startPolling() : stopPolling();
});
// Start polling initially if the page starts as visible
if (document.visibilityState === 'visible') {
startPolling();
}
It's a simple pattern, but it prevents those "why is my laptop fan screaming?" moments for your users.
📋 Practical Task
Build a Resource-Aware Stopwatch
Your task is to create a stopwatch that tracks elapsed time. However, to save system resources, the stopwatch should stop updating the DOM (the visual timer) whenever the tab is hidden, and it should log a message to the console stating "Pause: Tab Hidden" and "Resume: Tab Visible".
Requirements:
- Create a simple HTML page with a display for the timer (e.g.,
<div id="timer">0s</div>). - Implement a
setIntervalthat increments the timer every second. - Use the
visibilitychangeevent to stop the timer's UI updates when the tab is hidden and restart them when it becomes visible. - Ensure the actual elapsed time continues to be tracked internally, so when the user returns, the timer reflects the correct total time passed, even if the visual updates were paused.
There are no comments for now.