JavaScript Programming Labs

Master JavaScript through hands-on coding challenges. Write real code, get instant feedback, and build practical web development skills.

Error Handling, Modules & Storage - Module 6

Learn to handle errors gracefully, organize code with modules, and persist data in the browser.

Lab 16: Error Handling
Intermediate
Coding Challenge
Your Task: Master JavaScript error handling to write robust, reliable code. Proper error handling prevents crashes and provides meaningful feedback to users.

Detailed Requirements:

1. Use try/catch to handle errors - Wrap risky code in try blocks and catch exceptions.
try { // Code that might throw an error const result = riskyOperation(); console.log("Success:", result); } catch (error) { // Handle the error console.error("Error occurred:", error.message); }
2. Use the finally block - Code that runs regardless of success or failure (cleanup).
try { const file = openFile("data.txt"); processFile(file); } catch (error) { console.error("Failed to process file:", error); } finally { // Always runs - perfect for cleanup! closeFile(file); console.log("Cleanup complete"); }
3. Throw custom errors - Create and throw your own errors for validation.
function validateAge(age) { if (typeof age !== "number") { throw new TypeError("Age must be a number"); } if (age < 0 || age > 150) { throw new RangeError("Age must be between 0 and 150"); } return true; } try { validateAge("twenty"); // Will throw TypeError } catch (error) { console.error(error.name + ": " + error.message); }
4. Create custom Error classes - Extend Error for specific error types.
class ValidationError extends Error { constructor(message, field) { super(message); this.name = "ValidationError"; this.field = field; } } class NetworkError extends Error { constructor(message, statusCode) { super(message); this.name = "NetworkError"; this.statusCode = statusCode; } } throw new ValidationError("Invalid email format", "email");
5. Handle different error types - Use instanceof to handle specific errors.
try { doSomethingRisky(); } catch (error) { if (error instanceof TypeError) { console.error("Type error:", error.message); } else if (error instanceof RangeError) { console.error("Range error:", error.message); } else if (error instanceof ValidationError) { console.error("Validation failed on:", error.field); } else { console.error("Unknown error:", error); throw error; // Re-throw if we can't handle it } }
6. Access error properties - Use name, message, and stack trace.
try { throw new Error("Something went wrong!"); } catch (error) { console.log("Name:", error.name); // "Error" console.log("Message:", error.message); // "Something went wrong!" console.log("Stack:", error.stack); // Full stack trace }
💡 Pro Tips:
• Always catch specific error types when possible
• Use finally for cleanup (closing connections, files, etc.)
• Re-throw errors you can't handle properly
• Include helpful context in error messages
• Log stack traces in development, hide in production

⚠️ Common Mistakes to Avoid:
• Empty catch blocks (swallowing errors silently)
• Catching errors you can't handle properly
• Not providing useful error messages
• Using exceptions for control flow (use conditionals instead)

Expected Output:
Trying risky operation... Error caught: TypeError - Invalid input type Validation error on field: email Custom error handled! Cleanup complete in finally block

Requirements Checklist

Use try/catch to handle an error
Use a finally block for cleanup
Throw a custom error with throw new Error()
Create a custom Error class using extends
Use instanceof to check error type
Access error.name and error.message
Console Output
// Click "Run Code" to execute your JavaScript
Hints & Tips
• Try/catch: try { } catch (error) { }
• Finally: try { } catch { } finally { }
• Throw: throw new Error("message")
• Custom class: class MyError extends Error { }
• Check type: error instanceof TypeError
• Properties: error.name, error.message
Progress: 0/6
Score: 0/100
0%

Lab Results

Review feedback below

Lab 17: ES6 Modules
Intermediate
Coding Challenge
Your Task: Learn to organize code using ES6 modules. Modules help you split code into separate files, making it more maintainable and reusable.

Detailed Requirements:

1. Export named values - Export multiple items from a module.
// math.js export const PI = 3.14159; export function add(a, b) { return a + b; } export function multiply(a, b) { return a * b; } export class Calculator { // ... }
2. Import named exports - Import specific items by name.
// main.js import { PI, add, multiply } from "./math.js"; console.log(PI); // 3.14159 console.log(add(2, 3)); // 5 console.log(multiply(4, 5)); // 20 // Import with alias import { add as sum } from "./math.js"; console.log(sum(1, 2)); // 3
3. Export default value - One default export per module (the "main" thing).
// logger.js export default function log(message) { console.log(`[LOG] ${message}`); } // Or export a class as default export default class Logger { log(msg) { console.log(msg); } }
4. Import default exports - No curly braces needed, can name it anything.
// main.js import log from "./logger.js"; import myLogger from "./logger.js"; // Can use any name! log("Hello!"); myLogger("World!");
5. Combine default and named exports - A module can have both.
// utils.js export default function main() { } export const helper1 = () => { }; export const helper2 = () => { }; // Import both: import main, { helper1, helper2 } from "./utils.js";
6. Import all as namespace - Import everything under one object.
// main.js import * as MathUtils from "./math.js"; console.log(MathUtils.PI); console.log(MathUtils.add(1, 2)); console.log(MathUtils.multiply(3, 4));
💡 Pro Tips:
• Use named exports when module has multiple related items
• Use default export for the primary functionality
• File extension .js is required in browser imports
• Add type="module" to script tag: <script type="module">
• Modules are automatically in strict mode
• Modules are deferred by default (run after DOM loads)

⚠️ Common Mistakes to Avoid:
• Forgetting curly braces for named imports
• Using curly braces for default imports
• Circular dependencies between modules
• Missing type="module" in HTML

Expected Output:
Named export PI: 3.14159 add(2, 3) = 5 Default export called! Namespace import: MathUtils.multiply(4, 5) = 20

Requirements Checklist

Use export to create named exports
Use import { } to import named exports
Use export default for a default export
Import a default export (without curly braces)
Use import * as namespace syntax
Use as keyword to rename imports
Console Output
// Click "Run Code" to execute your JavaScript
Hints & Tips
• Named export: export const name = value
• Named import: import { name } from "./file.js"
• Default export: export default function() { }
• Default import: import name from "./file.js"
• Namespace: import * as Utils from "./file.js"
• Alias: import { old as new } from "./file.js"
Progress: 0/6
Score: 0/100
0%

Lab Results

Review feedback below

Lab 18: Local Storage & Session Storage
Intermediate
Coding Challenge
Your Task: Learn to persist data in the browser using Web Storage APIs. localStorage persists forever, sessionStorage clears when the tab closes.

Detailed Requirements:

1. Save data with localStorage.setItem() - Store key-value pairs (strings only!).
// Basic usage - stores strings localStorage.setItem("username", "john_doe"); localStorage.setItem("theme", "dark"); localStorage.setItem("volume", "80"); // Check if it worked console.log("Saved username:", localStorage.getItem("username"));
2. Retrieve data with localStorage.getItem() - Get values by key.
const username = localStorage.getItem("username"); const theme = localStorage.getItem("theme"); const nonExistent = localStorage.getItem("xyz"); // Returns null console.log(username); // "john_doe" console.log(nonExistent); // null // Always check for null! if (localStorage.getItem("theme")) { applyTheme(localStorage.getItem("theme")); }
3. Store objects using JSON - Convert to string with JSON.stringify().
// Storing objects/arrays const user = { name: "John", age: 30, preferences: ["dark mode", "notifications"] }; // Must stringify before storing! localStorage.setItem("user", JSON.stringify(user)); // Retrieve and parse const storedUser = JSON.parse(localStorage.getItem("user")); console.log(storedUser.name); // "John" console.log(storedUser.preferences[0]); // "dark mode"
4. Remove items with removeItem() and clear()
// Remove single item localStorage.removeItem("username"); // Clear ALL localStorage data (use carefully!) localStorage.clear(); // Check storage length console.log("Items stored:", localStorage.length);
5. Use sessionStorage for temporary data - Same API, clears on tab close.
// Identical API to localStorage sessionStorage.setItem("tempData", "This disappears on tab close"); const temp = sessionStorage.getItem("tempData"); // Use for: // - Form data in progress // - Single-session authentication // - Temporary UI state
6. Handle storage errors and check availability
// Check if localStorage is available function storageAvailable() { try { const test = "__storage_test__"; localStorage.setItem(test, test); localStorage.removeItem(test); return true; } catch (e) { return false; } } // Safe storage wrapper function safeSetItem(key, value) { try { localStorage.setItem(key, JSON.stringify(value)); return true; } catch (error) { console.error("Storage error:", error.message); return false; // Quota exceeded or private browsing } }
💡 Pro Tips:
• localStorage limit is ~5-10MB per origin
• Always use try/catch (private browsing may block storage)
• Use JSON.parse/stringify for objects and arrays
• Check for null when retrieving data
• Consider using a wrapper function for common operations
• Storage events fire across tabs: window.addEventListener("storage", handler)

⚠️ Common Mistakes to Avoid:
• Storing objects directly without JSON.stringify()
• Not handling null returns from getItem()
• Storing sensitive data (it's not secure!)
• Not catching quota exceeded errors

Expected Output:
Saved: username = john_doe Retrieved: john_doe Stored object: { name: "John", age: 30 } Parsed user.name: John Items in storage: 2 Removed username, remaining: 1

Requirements Checklist

Use localStorage.setItem() to store data
Use localStorage.getItem() to retrieve data
Use JSON.stringify() to store an object
Use JSON.parse() to retrieve an object
Use localStorage.removeItem() or clear()
Use sessionStorage for temporary data
Console Output
// Click "Run Code" to execute your JavaScript
Hints & Tips
• Save: localStorage.setItem("key", "value")
• Get: localStorage.getItem("key")
• Store object: JSON.stringify(obj)
• Parse object: JSON.parse(string)
• Remove: localStorage.removeItem("key")
• Session: sessionStorage.setItem("key", "value")
Progress: 0/6
Score: 0/100
0%

Lab Results

Review feedback below