Learnitweb

Understanding Synchronous and Asynchronous Programming in JavaScript

1. A Real-Life Analogy: The Birthday Cake Story

Let’s start with a situation from daily life.

Your best friend has a birthday party tonight. He asks you to bring the cake because your mom works at the best pastry shop in town. At 4 PM, you call your mom and ask her to start baking the cake. It will take one hour to prepare.

Now there are two ways this situation can unfold.

2. Synchronous Way (Blocking)

In the synchronous approach:

  1. You call your mom.
  2. You stay on the phone for one full hour.
  3. You are not allowed to hang up.
  4. Only after the cake is ready can you go and pick it up.

Key observation

  • You cannot do anything else while waiting.
  • The waiting time blocks you completely.

This is exactly how synchronous code behaves.

3. Asynchronous Way (Non-Blocking)

In the asynchronous approach:

  1. You call your mom.
  2. You ask her to call you back when the cake is ready.
  3. You hang up immediately.
  4. You watch Netflix, play games, or go for ice cream 🍦.
  5. When the cake is ready, your mom calls you back.

Key observation

  • You are free to do other work while waiting.
  • You only react when the task finishes.

This is how asynchronous code works.

4. Why JavaScript Loves Asynchronous Programming

Many programming languages force you to work synchronously.

JavaScript, however, is designed to be non-blocking by default, which makes it ideal for:

  • Web applications
  • Servers
  • APIs
  • File operations
  • Network requests

This is one of the biggest reasons JavaScript is so powerful.

5. Synchronous vs Asynchronous: Conceptual Difference

Synchronous Execution

  • Code runs line by line
  • Each step must finish before the next starts
  • Long tasks block the entire program

Asynchronous Execution

  • Long tasks are started, not waited for
  • Program continues executing the next lines
  • Completion is handled later using callbacks, promises, or async/await

6. A JavaScript Example: Printing Numbers

Let’s now see a real JavaScript example that demonstrates this behavior.

Goal

Print the numbers:

1
2
3
4

We create four functions, each responsible for printing one number.

const fs = require("fs");

function printOne() {
  const num = 1;
  console.log(num);
}

function getNumberTwo() {
  return 2;
}

function printTwo() {
  const num = getNumberTwo();
  console.log(num);
}

function printThree() {
  fs.readFile("./numberThree.txt", "utf8", (err, data) => {
    if (err) {
      console.error(err);
      return;
    }
    console.log(3);
  });
}

function printFour() {
  const num = 4;
  console.log(num);
}

printOne();
printTwo();
printThree();
printFour();

Actual Output

1
2
4
3

7. Understanding What Happened

Let’s break it down step by step.

Execution Order Explained

  1. printOne() → prints 1
  2. printTwo() → prints 2
  3. printThree()
    • Starts reading the file
    • Does NOT wait
    • Returns immediately
  4. printFour() → prints 4
  5. File reading finishes
  6. Callback executes → prints 3

8. Blocking vs Non-Blocking Calls

Blocking (Synchronous)

  • Program waits
  • Nothing else executes
  • Example: getNumberTwo()

Non-Blocking (Asynchronous)

  • Program continues immediately
  • Result handled later
  • Example: fs.readFile()

9. Visualizing Execution Flow

Synchronous Flow

Statement 1
Statement 2  ----> waits until finished
Statement 3
Statement 4

Asynchronous Flow

Statement 1
Statement 2
Async Call ----> starts
Statement 3
Statement 4
(callback runs later)

10. Common Asynchronous Operations in JavaScript

  • setTimeout
  • HTTP requests
  • Reading/writing files
  • Database queries
  • Network communication

11. Why Callbacks Execute Last

JavaScript first finishes all synchronous code.

Only after that does it execute:

  • Callbacks
  • Timers
  • I/O results

This is why printThree finishes after printFour.