Codcups
Progress: 0%

01. ๐Ÿš€ JavaScript Fundamentals

JavaScript is a versatile, high-level programming language that powers interactive websites, web applications, servers (Node.js), and even mobile apps. It's the language of the web!

What is JavaScript?

JavaScript (often abbreviated as JS) is a lightweight, interpreted programming language with first-class functions. It was created in 1995 by Brendan Eich and has evolved into one of the most important programming languages on the web.

JavaScript in the Browser

  • Client-side scripting: Runs in user's browser
  • Interactive web pages: Dynamic content updates
  • Event handling: User interactions like clicks
  • DOM manipulation: Changing HTML/CSS dynamically
  • API communication: Fetching data from servers
Key Concept: JavaScript is single-threaded but uses an event loop and callback queue for asynchronous operations. This allows it to handle multiple tasks without freezing.

Example: Your First JavaScript Program

// This is a single-line comment

/* 
   This is a multi-line comment
   JavaScript code goes between script tags or in .js files
*/

// Output to browser console (for debugging)
console.log("Hello, JavaScript!");

// Alert popup (not recommended for production)
alert("Welcome to JavaScript!");

// Write to HTML document
document.write("

JavaScript is awesome!

"); // Changing HTML content document.getElementById("demo").innerHTML = "Content changed with JS!"; // Simple calculation let sum = 5 + 3; console.log("5 + 3 = " + sum); // Function example function greet(name) { return "Hello, " + name + "!"; } console.log(greet("Developer"));

Note: JavaScript is case-sensitive. Always check your console (F12) for errors and debug messages. Semicolons are optional but recommended.

Interactive Demo
Click buttons to see JavaScript in action!

02. ๐Ÿ“ฆ Variables & Data Types

Variables are containers for storing data values. JavaScript is dynamically typed, meaning you don't need to specify the data type when declaring a variable.

Variable Declaration Methods

  • var: Old way, function-scoped
  • let: Modern, block-scoped
  • const: Constant, cannot be reassigned

JavaScript Data Types

Primitive Types:
1. String: Text values
2. Number: Integer and floating-point
3. Boolean: true/false
4. Undefined: Variable declared but not assigned
5. Null: Intentional absence of value
6. Symbol: Unique identifier (ES6)
7. BigInt: Large integers (ES2020)

Example: Variables and Data Types

// Variable declarations
var oldWay = "Using var (avoid in modern JS)";
let modernWay = "Using let (preferred)";
const constantValue = "Cannot be reassigned";

// Different data types
let stringType = "Hello World"; // String
let numberType = 42; // Number
let floatType = 3.14; // Floating point
let booleanType = true; // Boolean
let undefinedType; // Undefined
let nullType = null; // Null

// Type checking
console.log(typeof stringType); // "string"
console.log(typeof numberType); // "number"
console.log(typeof booleanType); // "boolean"
console.log(typeof undefinedType); // "undefined"
console.log(typeof nullType); // "object" (historical bug!)

// Type conversion
let str = "123";
let num = Number(str); // Convert to number
console.log(num); // 123

let num2 = 456;
let str2 = String(num2); // Convert to string
console.log(str2); // "456"

// Template literals (ES6)
let name = "Alice";
let age = 25;
let greeting = `Hello, my name is ${name} and I am ${age} years old.`;
console.log(greeting);
Variable Demo
Click buttons to see variable operations

03. โž• Operators & Expressions

Operators perform operations on variables and values. JavaScript has a rich set of operators for arithmetic, comparison, logical, and assignment operations.

Operator Types

  • Arithmetic: +, -, *, /, %, **
  • Assignment: =, +=, -=, *=, /=
  • Comparison: ==, ===, !=, !==, >, <, >=, <=
  • Logical: &&, ||, !
  • Bitwise: &, |, ^, ~, <<, >>, >>>
  • Ternary: ? : (conditional operator)
Key Concept: Use === (strict equality) instead of == (loose equality) to avoid unexpected type coercion. === checks both value and type.

Example: JavaScript Operators

// Arithmetic operators
let a = 10, b = 3;
console.log(a + b); // 13 (addition)
console.log(a - b); // 7 (subtraction)
console.log(a * b); // 30 (multiplication)
console.log(a / b); // 3.333... (division)
console.log(a % b); // 1 (remainder/modulus)
console.log(a ** b); // 1000 (exponentiation)

// Assignment operators
let x = 5;
x += 3; // x = x + 3
console.log(x); // 8

x *= 2; // x = x * 2
console.log(x); // 16

// Comparison operators
console.log(5 == "5"); // true (loose equality)
console.log(5 === "5"); // false (strict equality)
console.log(5 != "5"); // false
console.log(5 !== "5"); // true
console.log(10 > 5); // true

// Logical operators
let isLoggedIn = true;
let hasPermission = false;
console.log(isLoggedIn && hasPermission); // false (AND)
console.log(isLoggedIn || hasPermission); // true (OR)
console.log(!isLoggedIn); // false (NOT)

// Ternary operator
let age = 18;
let canVote = age >= 18 ? "Yes" : "No";
console.log(canVote); // "Yes"

// Nullish coalescing (ES2020)
let userInput = null;
let value = userInput ?? "Default Value";
console.log(value); // "Default Value"

// Optional chaining (ES2020)
let user = {
    profile: {
        name: "John"
    }
};
console.log(user.profile?.name); // "John"
console.log(user.address?.city); // undefined (no error)
Operator Calculator
Enter numbers and select operator

04. ๐Ÿšฆ Control Flow Statements

Control flow statements determine the order in which code is executed. JavaScript provides several ways to control program flow.

Conditional Statements

  • if/else: Basic conditional execution
  • else if: Multiple conditions
  • switch: Multi-way branching
  • Ternary: Conditional expression

Looping Statements

Loops allow code to be executed repeatedly:
1. for: Counter-controlled loops
2. while: Condition-controlled loops
3. do...while: Post-test loops
4. for...of: Iterate over iterables
5. for...in: Iterate over object properties

Example: Control Flow in JavaScript

// If-else statement
let temperature = 25;

if (temperature > 30) {
    console.log("It's hot outside!");
} else if (temperature > 20) {
    console.log("It's warm outside!");
} else if (temperature > 10) {
    console.log("It's cool outside!");
} else {
    console.log("It's cold outside!");
}

// Switch statement
let day = "Monday";
switch(day) {
    case "Monday":
        console.log("Start of work week");
        break;
    case "Friday":
        console.log("Weekend is coming!");
        break;
    case "Saturday":
    case "Sunday":
        console.log("It's weekend!");
        break;
    default:
        console.log("It's a regular day");
}

// For loop
console.log("Counting 1 to 5:");
for (let i = 1; i <= 5; i++) {
    console.log(i);
}

// While loop
let count = 1;
console.log("While loop:");
while (count <= 3) {
    console.log(`Count: ${count}`);
    count++;
}

// Do-while loop
let number;
do {
    number = Math.floor(Math.random() * 10);
    console.log(`Random number: ${number}`);
} while (number !== 5);

// For...of loop (ES6)
let fruits = ["Apple", "Banana", "Cherry"];
console.log("Fruits array:");
for (let fruit of fruits) {
    console.log(fruit);
}

// For...in loop (for objects)
let person = {name: "John", age: 30, city: "New York"};
console.log("Person object properties:");
for (let key in person) {
    console.log(`${key}: ${person[key]}`);
}

// Break and continue
console.log("Break and continue example:");
for (let i = 1; i <= 10; i++) {
    if (i === 5) continue; // Skip 5
    if (i === 8) break; // Stop at 8
    console.log(i);
}
Control Flow Demo
Select a demo to see control flow in action

05. โš™๏ธ Functions in JavaScript

Functions are reusable blocks of code that perform specific tasks. They are fundamental building blocks in JavaScript programming.

Function Types

  • Function Declaration: Traditional function definition
  • Function Expression: Function assigned to variable
  • Arrow Function: Compact ES6 syntax
  • IIFE: Immediately Invoked Function Expression
  • Higher-order Functions: Functions that take/return functions

Function Parameters & Arguments

Functions can accept parameters (placeholders) and be called with arguments (actual values). Default parameters, rest parameters, and destructuring are powerful ES6+ features.

Example: Functions in JavaScript

// Function declaration (hoisted)
function greet(name) {
    return `Hello, ${name}!`;
}
console.log(greet("Alice"));

// Function expression
const multiply = function(a, b) {
    return a * b;
};
console.log(multiply(5, 3));

// Arrow function (ES6)
const divide = (a, b) => a / b;
console.log(divide(10, 2));

// Arrow function with multiple statements
const calculateArea = (width, height) => {
    const area = width * height;
    return `Area: ${area}`;
};
console.log(calculateArea(5, 4));

// Default parameters
function greetUser(name = "Guest") {
    return `Welcome, ${name}!`;
}
console.log(greetUser()); // "Welcome, Guest!"
console.log(greetUser("Bob")); // "Welcome, Bob!"

// Rest parameters (...)
function sum(...numbers) {
    return numbers.reduce((total, num) => total + num, 0);
}
console.log(sum(1, 2, 3, 4, 5)); // 15

// Higher-order function
function createMultiplier(factor) {
    return function(number) {
        return number * factor;
    };
}

const double = createMultiplier(2);
const triple = createMultiplier(3);

console.log(double(5)); // 10
console.log(triple(5)); // 15

// IIFE (Immediately Invoked Function Expression)
(function() {
    console.log("IIFE executed immediately!");
})();

// Callback function
function processArray(arr, callback) {
    const result = [];
    for (let item of arr) {
        result.push(callback(item));
    }
    return result;
}

const numbers = [1, 2, 3, 4];
const squared = processArray(numbers, x => x * x);
console.log(squared); // [1, 4, 9, 16]

// Recursive function
function factorial(n) {
    if (n <= 1) return 1;
    return n * factorial(n - 1);
}
console.log(factorial(5)); // 120
Function Calculator
Select operation and click Calculate

06. ๐Ÿ—ƒ๏ธ Arrays & Array Methods

Arrays are special variables that can hold multiple values. JavaScript arrays are dynamic, can contain mixed types, and have powerful built-in methods.

Array Creation Methods

  • Array literal: []
  • Array constructor: new Array()
  • Array.of(): Creates array from arguments
  • Array.from(): Creates from array-like objects

Common Array Methods

JavaScript provides many array methods for manipulation:
1. Mutator methods: Change original array (push, pop, splice)
2. Accessor methods: Return new array/values (slice, concat, indexOf)
3. Iteration methods: Process each element (forEach, map, filter)
4. ES6+ methods: find, findIndex, includes, flat, flatMap

Example: Working with Arrays

// Creating arrays
let fruits = ["Apple", "Banana", "Orange"];
let numbers = [1, 2, 3, 4, 5];
let mixed = ["Hello", 42, true, null];

// Accessing elements
console.log(fruits[0]); // "Apple"
console.log(fruits.length); // 3

// Adding/removing elements
fruits.push("Mango"); // Add to end
console.log(fruits); // ["Apple", "Banana", "Orange", "Mango"]

fruits.pop(); // Remove from end
console.log(fruits); // ["Apple", "Banana", "Orange"]

fruits.unshift("Strawberry"); // Add to beginning
console.log(fruits); // ["Strawberry", "Apple", "Banana", "Orange"]

fruits.shift(); // Remove from beginning
console.log(fruits); // ["Apple", "Banana", "Orange"]

// Slicing and splicing
let citrus = fruits.slice(1, 3); // Returns new array
console.log(citrus); // ["Banana", "Orange"]

fruits.splice(1, 1, "Grapes", "Kiwi"); // Modify original
console.log(fruits); // ["Apple", "Grapes", "Kiwi", "Orange"]

// Iteration methods
console.log("For each fruit:");
fruits.forEach((fruit, index) => {
    console.log(`${index + 1}. ${fruit}`);
});

// Map method (returns new array)
let upperFruits = fruits.map(fruit => fruit.toUpperCase());
console.log(upperFruits); // ["APPLE", "GRAPES", "KIWI", "ORANGE"]

// Filter method
let longFruits = fruits.filter(fruit => fruit.length > 5);
console.log(longFruits); // ["Grapes", "Orange"]

// Reduce method
let numbersArray = [1, 2, 3, 4, 5];
let sum = numbersArray.reduce((total, num) => total + num, 0);
console.log("Sum:", sum); // 15

// Find method (ES6)
let found = fruits.find(fruit => fruit.startsWith("K"));
console.log("Found:", found); // "Kiwi"

// Spread operator (ES6)
let moreFruits = [...fruits, "Pineapple", "Watermelon"];
console.log(moreFruits);

// Destructuring (ES6)
let [first, second, ...rest] = fruits;
console.log(first); // "Apple"
console.log(second); // "Grapes"
console.log(rest); // ["Kiwi", "Orange"]

// Multi-dimensional arrays
let matrix = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]
];
console.log(matrix[1][2]); // 6
Array Operations
Click buttons to see array operations

07. ๐Ÿ—๏ธ Objects & Object-Oriented JavaScript

Objects are collections of key-value pairs and are fundamental to JavaScript. Almost everything in JavaScript is an object!

Object Creation Methods

  • Object literal: {}
  • Constructor function: new Object()
  • Object.create(): Prototype-based creation
  • Class syntax: ES6 class keyword

Object-Oriented JavaScript

JavaScript uses prototype-based inheritance rather than class-based inheritance. However, ES6 introduced class syntax as syntactic sugar over prototypes.

Example: Objects in JavaScript

// Object literal
let person = {
    firstName: "John",
    lastName: "Doe",
    age: 30,
    isStudent: false,
    
    // Method (function inside object)
    getFullName: function() {
        return `${this.firstName} ${this.lastName}`;
    },
    
    // ES6 method shorthand
    greet() {
        return `Hello, my name is ${this.firstName}`;
    }
};

// Accessing properties
console.log(person.firstName); // "John"
console.log(person["lastName"]); // "Doe"
console.log(person.getFullName()); // "John Doe"

// Adding/updating properties
person.email = "john@example.com";
person.age = 31;

// Deleting properties
delete person.isStudent;

// Object.keys(), Object.values(), Object.entries()
console.log(Object.keys(person)); // ["firstName", "lastName", "age", "getFullName", "greet", "email"]
console.log(Object.values(person)); // ["John", "Doe", 31, function...]
console.log(Object.entries(person)); // Array of key-value pairs

// Constructor function (old way)
function Car(make, model, year) {
    this.make = make;
    this.model = model;
    this.year = year;
    
    this.getInfo = function() {
        return `${this.year} ${this.make} ${this.model}`;
    };
}

let myCar = new Car("Toyota", "Camry", 2020);
console.log(myCar.getInfo());

// ES6 Class syntax
class Animal {
    constructor(name, species) {
        this.name = name;
        this.species = species;
    }
    
    makeSound() {
        return `${this.name} makes a sound`;
    }
    
    // Static method
    static isAnimal(obj) {
        return obj instanceof Animal;
    }
}

class Dog extends Animal {
    constructor(name, breed) {
        super(name, "Dog");
        this.breed = breed;
    }
    
    makeSound() {
        return `${this.name} barks!`;
    }
    
    wagTail() {
        return `${this.name} wags tail happily`;
    }
}

let myDog = new Dog("Buddy", "Golden Retriever");
console.log(myDog.makeSound()); // "Buddy barks!"
console.log(myDog.wagTail()); // "Buddy wags tail happily"
console.log(Animal.isAnimal(myDog)); // true

// Object destructuring (ES6)
let {firstName, age} = person;
console.log(firstName, age); // "John" 31

// Spread operator with objects (ES2018)
let updatedPerson = {...person, city: "New York", age: 32};
console.log(updatedPerson);

// Optional chaining (ES2020)
let user = {
    profile: {
        name: "Alice",
        address: {
            city: "Boston"
        }
    }
};
console.log(user.profile?.address?.city); // "Boston"
console.log(user.profile?.phone?.number); // undefined (no error)

// Computed property names
let propName = "favoriteColor";
let dynamicObj = {
    [propName]: "Blue",
    ["is" + "Valid"]: true
};
console.log(dynamicObj.favoriteColor); // "Blue"
Object Operations
Click buttons to explore object features

08. ๐ŸŒ DOM Manipulation

The Document Object Model (DOM) is a programming interface for HTML and XML documents. It represents the page so that programs can change document structure, style, and content.

DOM Selection Methods

  • getElementById(): Select by ID
  • getElementsByClassName(): Select by class
  • getElementsByTagName(): Select by tag
  • querySelector(): CSS selector (single)
  • querySelectorAll(): CSS selector (all)

DOM Manipulation Operations

You can manipulate the DOM in many ways:
1. Content: innerHTML, textContent, innerText
2. Attributes: getAttribute, setAttribute
3. Styles: style property, classList
4. Structure: createElement, appendChild, removeChild
5. Events: addEventListener, removeEventListener

Example: DOM Manipulation

// DOM Selection
let heading = document.getElementById("main-heading");
let paragraphs = document.getElementsByClassName("content");
let buttons = document.getElementsByTagName("button");
let firstItem = document.querySelector(".list-item");
let allItems = document.querySelectorAll(".list-item");

// Changing content
heading.textContent = "New Heading Text";
heading.innerHTML = "Formatted Heading";

// Changing styles
heading.style.color = "blue";
heading.style.fontSize = "24px";
heading.classList.add("highlight"); // Add CSS class
heading.classList.remove("old-class"); // Remove CSS class
heading.classList.toggle("active"); // Toggle CSS class

// Creating new elements
let newParagraph = document.createElement("p");
newParagraph.textContent = "This is a new paragraph";
newParagraph.className = "new-content";

// Adding to DOM
document.body.appendChild(newParagraph);
let container = document.getElementById("container");
container.appendChild(newParagraph);

// Inserting at specific position
let referenceElement = document.getElementById("reference");
container.insertBefore(newParagraph, referenceElement);

// Removing elements
let oldElement = document.getElementById("old");
if (oldElement) {
    oldElement.remove();
    // or: oldElement.parentNode.removeChild(oldElement);
}

// Working with attributes
let image = document.querySelector("img");
image.setAttribute("alt", "Description of image");
let altText = image.getAttribute("alt");
image.hasAttribute("src"); // true/false
image.removeAttribute("title");

// Event handling
let button = document.getElementById("myButton");

// Traditional way
button.onclick = function() {
    console.log("Button clicked!");
};

// Modern way (allows multiple handlers)
button.addEventListener("click", function(event) {
    console.log("Button clicked via addEventListener!");
    console.log("Event type:", event.type);
    console.log("Target:", event.target);
});

// Event delegation (efficient for multiple elements)
document.addEventListener("click", function(event) {
    if (event.target.classList.contains("item")) {
        console.log("Item clicked:", event.target.textContent);
    }
});

// Form handling
let form = document.getElementById("myForm");
form.addEventListener("submit", function(event) {
    event.preventDefault(); // Prevent page reload
    let input = document.getElementById("username");
    console.log("Username:", input.value);
});

// Working with input events
let searchInput = document.getElementById("search");
searchInput.addEventListener("input", function(event) {
    console.log("Search term:", event.target.value);
});

// Keyboard events
document.addEventListener("keydown", function(event) {
    console.log("Key pressed:", event.key);
    if (event.key === "Escape") {
        console.log("Escape pressed!");
    }
});

// Mouse events
let box = document.getElementById("box");
box.addEventListener("mouseenter", function() {
    this.style.backgroundColor = "lightblue";
});
box.addEventListener("mouseleave", function() {
    this.style.backgroundColor = "";
});
DOM Manipulation Playground

DOM Manipulation Demo

This is a paragraph that can be modified.

  • Item 1
  • Item 2

09. โญ ES6+ Modern JavaScript

ECMAScript 6 (ES6) and later versions introduced significant improvements to JavaScript. These modern features make code cleaner, more readable, and more powerful.

Key ES6+ Features

  • let & const: Block-scoped variables
  • Arrow functions: Concise function syntax
  • Template literals: String interpolation
  • Destructuring: Extract values from arrays/objects
  • Spread/Rest operators: ... syntax
  • Classes: Syntactic sugar for prototypes
  • Modules: import/export statements

ES7-ES2023 Features

Later ECMAScript versions added more useful features:
- ES7: Exponentiation operator, Array.includes()
- ES8: async/await, Object.values(), Object.entries()
- ES2019: flat(), flatMap(), optional catch binding
- ES2020: BigInt, optional chaining, nullish coalescing
- ES2021: replaceAll(), logical assignment operators
- ES2022: Top-level await, class fields

Example: Modern JavaScript Features

// ES6: let and const
let variable = "can be reassigned";
const constant = "cannot be reassigned";

// ES6: Arrow functions
const add = (a, b) => a + b;
const square = x => x * x;

// ES6: Template literals
let name = "Alice";
let age = 25;
let greeting = `Hello, ${name}! You are ${age} years old.`;

// ES6: Destructuring
let [first, second] = [1, 2, 3, 4];
let {title, author} = {title: "Book", author: "Author", year: 2023};

// ES6: Spread operator
let arr1 = [1, 2, 3];
let arr2 = [...arr1, 4, 5]; // [1, 2, 3, 4, 5]

let obj1 = {a: 1, b: 2};
let obj2 = {...obj1, c: 3}; // {a: 1, b: 2, c: 3}

// ES6: Rest parameters
function sum(...numbers) {
    return numbers.reduce((total, num) => total + num, 0);
}

// ES6: Default parameters
function greet(person = "Guest") {
    return `Hello, ${person}!`;
}

// ES6: Classes
class Rectangle {
    constructor(width, height) {
        this.width = width;
        this.height = height;
    }
    
    get area() {
        return this.width * this.height;
    }
    
    static createSquare(side) {
        return new Rectangle(side, side);
    }
}

// ES6: Modules (in separate files)
// export const PI = 3.14159;
// export function circleArea(radius) { return PI * radius * radius; }
// import { PI, circleArea } from './math.js';

// ES7: Exponentiation operator
let cube = 2 ** 3; // 8

// ES7: Array.includes()
let fruits = ["apple", "banana", "orange"];
console.log(fruits.includes("banana")); // true

// ES8: async/await (see next section)
// ES8: Object.values(), Object.entries()
let person = {name: "John", age: 30};
console.log(Object.values(person)); // ["John", 30]
console.log(Object.entries(person)); // [["name", "John"], ["age", 30]]

// ES2019: flat(), flatMap()
let nested = [1, 2, [3, 4, [5, 6]]];
console.log(nested.flat(2)); // [1, 2, 3, 4, 5, 6]

// ES2020: Optional chaining
let user = {profile: {name: "Alice"}};
console.log(user.profile?.name); // "Alice"
console.log(user.contact?.phone); // undefined

// ES2020: Nullish coalescing
let input = null;
let value = input ?? "default"; // "default"

// ES2021: replaceAll()
let text = "Hello World World";
console.log(text.replaceAll("World", "JavaScript")); // "Hello JavaScript JavaScript"

// ES2021: Logical assignment operators
let x = 0;
x ||= 5; // x = x || 5 (x becomes 5)
x &&= 10; // x = x && 10 (x becomes 10)

// ES2022: Top-level await (in modules)
// const data = await fetch(url);

// ES2022: Class fields
class Counter {
    count = 0; // Instance field
    
    increment() {
        this.count++;
    }
    
    static version = "1.0"; // Static field
}

// Private class fields (ES2022)
class BankAccount {
    #balance = 0; // Private field
    
    deposit(amount) {
        this.#balance += amount;
    }
    
    getBalance() {
        return this.#balance;
    }
}
ES6+ Features Demo
Click buttons to see modern JavaScript features

10. โณ Asynchronous JavaScript

Asynchronous programming allows JavaScript to handle time-consuming operations without blocking the main thread. This is essential for network requests, file operations, and timers.

Async Techniques

  • Callbacks: Traditional async approach
  • Promises: ES6 solution for async operations
  • async/await: ES8 syntactic sugar for promises
  • Event Loop: JavaScript's concurrency model

The Event Loop

JavaScript has a single-threaded event loop architecture:
1. Call Stack: Executes synchronous code
2. Web APIs: Handle async operations (setTimeout, fetch)
3. Callback Queue: Stores completed async callbacks
4. Event Loop: Moves callbacks from queue to stack when stack is empty

Example: Asynchronous JavaScript

// Callbacks (traditional)
function fetchData(callback) {
    setTimeout(() => {
        const data = { id: 1, name: "John Doe" };
        callback(null, data); // Error-first callback pattern
    }, 1000);
}

fetchData((error, data) => {
    if (error) {
        console.error("Error:", error);
    } else {
        console.log("Data received:", data);
    }
});

// Promises (ES6)
function fetchUser(id) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            if (id > 0) {
                resolve({ id, name: `User ${id}` });
            } else {
                reject(new Error("Invalid ID"));
            }
        }, 1000);
    });
}

// Using promises
fetchUser(1)
    .then(user => {
        console.log("User:", user);
        return user.name;
    })
    .then(name => {
        console.log("Name:", name);
    })
    .catch(error => {
        console.error("Error:", error.message);
    })
    .finally(() => {
        console.log("Request completed");
    });

// Promise.all (parallel execution)
const promise1 = fetchUser(1);
const promise2 = fetchUser(2);
const promise3 = fetchUser(3);

Promise.all([promise1, promise2, promise3])
    .then(users => {
        console.log("All users:", users);
    })
    .catch(error => {
        console.error("One request failed:", error);
    });

// Promise.race (first to settle)
Promise.race([promise1, promise2])
    .then(firstUser => {
        console.log("First user received:", firstUser);
    });

// Promise.allSettled (all complete, regardless of success)
Promise.allSettled([promise1, fetchUser(-1), promise3])
    .then(results => {
        results.forEach(result => {
            if (result.status === "fulfilled") {
                console.log("Success:", result.value);
            } else {
                console.log("Failed:", result.reason.message);
            }
        });
    });

// Async/await (ES8)
async function getUserData(id) {
    try {
        console.log("Fetching user...");
        const user = await fetchUser(id);
        console.log("User received:", user);
        
        // Sequential async operations
        const posts = await fetchPosts(user.id);
        const comments = await fetchComments(user.id);
        
        return { user, posts, comments };
    } catch (error) {
        console.error("Failed to fetch data:", error.message);
        throw error; // Re-throw for caller to handle
    } finally {
        console.log("Async operation complete");
    }
}

// Using async/await
(async function() {
    try {
        const data = await getUserData(1);
        console.log("Complete data:", data);
    } catch (error) {
        console.error("Main error:", error);
    }
})();

// Fetch API (modern alternative to XMLHttpRequest)
async function fetchFromAPI() {
    try {
        const response = await fetch('https://jsonplaceholder.typicode.com/posts/1');
        
        if (!response.ok) {
            throw new Error(`HTTP error! status: ${response.status}`);
        }
        
        const data = await response.json();
        console.log("API Data:", data);
        return data;
    } catch (error) {
        console.error("Fetch error:", error);
    }
}

// setTimeout and setInterval
console.log("Start");

setTimeout(() => {
    console.log("This runs after 2 seconds");
}, 2000);

let counter = 0;
const intervalId = setInterval(() => {
    counter++;
    console.log(`Interval ${counter}`);
    
    if (counter === 5) {
        clearInterval(intervalId);
        console.log("Interval stopped");
    }
}, 500);

console.log("End");

// Event loop demonstration
console.log("Script start"); // 1

setTimeout(() => {
    console.log("setTimeout"); // 4
}, 0);

Promise.resolve()
    .then(() => {
        console.log("Promise 1"); // 3
    })
    .then(() => {
        console.log("Promise 2"); // 3.5
    });

console.log("Script end"); // 2

// Output order:
// 1. Script start
// 2. Script end
// 3. Promise 1
// 4. Promise 2
// 5. setTimeout
Async Operations Demo
Click buttons to test async operations