JavaScript Tutorial

Do While Loop in JavaScript: Syntax, Examples and Best Practices

Master the JavaScript do...while loop with clear syntax breakdown, real-world examples, comparison with while loop, loop control with break and continue, common mistakes, and best practices.

Welcome back! šŸ‘‹ In the previous lesson, you mastered the while loop — perfect for condition-driven repetition. Now let's explore its close cousin — the do...while loop!

The do...while loop has one key superpower that sets it apart: it always runs the body at least once, no matter what. The condition is checked only after the first execution. This makes it the perfect tool for menus, prompts, validation, and any situation where "try it first, then decide" is the right approach.

Let's break it down completely!


What is a do...while Loop?

A do...while loop executes its body first, then checks the condition. If the condition is true, it repeats. If false, it stops — but the body has already run at least once.

let count = 1;

do {
  console.log("Count:", count);
  count++;
} while (count <= 5);

// Output:
// Count: 1
// Count: 2
// Count: 3
// Count: 4
// Count: 5

Syntax

do {
  // code to repeat
  // runs at least once — ALWAYS!
} while (condition);
  • do { } — the body that always runs first, before any condition check
  • condition — evaluated after the body runs; if true the body repeats, if false the loop exits
  • ; — don't forget the semicolon after the closing while (condition) — it's required!

The Key Difference: Condition Checked After

This is what makes do...while unique. The condition sits at the bottom, not the top.

let x = 100; // Condition will be false immediately

// while — checks condition FIRST, body never runs
while (x < 5) {
  console.log("while body ran"); // Never prints
}

// do...while — runs body FIRST, then checks condition
do {
  console.log("do...while body ran"); // Prints ONCE āœ…
} while (x < 5);

// Output: do...while body ran

Think of it this way:

  • while → "Should I do this?" then do it
  • do...while → "Do it!" then "Should I do it again?"

How JavaScript Executes a do...while Loop

let i = 1;

do {
  console.log(i);
  i++;
} while (i <= 4);

Step by step:

  • Step 1: Run body → print 1 → i++ → i = 2
  • Step 2: Is 2 <= 4? āœ… Yes → run body → print 2 → i++ → i = 3
  • Step 3: Is 3 <= 4? āœ… Yes → run body → print 3 → i++ → i = 4
  • Step 4: Is 4 <= 4? āœ… Yes → run body → print 4 → i++ → i = 5
  • Step 5: Is 5 <= 4? āŒ No → exit loop

Notice: the body ran before any condition was ever checked — that's the do...while guarantee.


do...while vs while — Side by Side

// Scenario: condition is FALSE from the very start

let n = 10;

// while — body SKIPPED entirely
while (n < 5) {
  console.log("while ran"); // Never executes
}

// do...while — body runs ONCE regardless
do {
  console.log("do...while ran"); // Runs once āœ…
} while (n < 5);
Featurewhiledo...while
Condition checkedBefore first runAfter first run
Minimum executions0 (may never run)1 (always runs once)
Best forCondition may be false upfrontMust run body at least once
Semicolon afterNot neededRequired after while(...)
ReadabilityCondition visible at topBody intent clear first

Real-World Examples

Example 1: Menu System

The most classic do...while use case — show a menu at least once, then repeat based on the user's choice.

// Simulated user choices
let choices = [1, 2, 3, 4]; // 1=View, 2=Add, 3=Delete, 4=Exit
let step = 0;
let choice;

do {
  choice = choices[step++];

  console.log("\nšŸ“‹ MAIN MENU");
  console.log("1. View Items");
  console.log("2. Add Item");
  console.log("3. Delete Item");
  console.log("4. Exit");
  console.log(`\nYou chose: ${choice}`);

  switch (choice) {
    case 1: console.log("šŸ“„ Showing all items..."); break;
    case 2: console.log("āž• Adding new item..."); break;
    case 3: console.log("šŸ—‘ļø Deleting item..."); break;
    case 4: console.log("šŸ‘‹ Goodbye!"); break;
    default: console.log("āŒ Invalid choice. Try again.");
  }

} while (choice !== 4);

// Output: Menu displays all 4 times, exits on choice 4

Example 2: Input Validation (Simulate Until Valid)

// Simulated inputs — first two invalid, third valid
let inputs = [-5, 0, 42];
let index = 0;
let userInput;

do {
  userInput = inputs[index++];
  console.log(`Input received: ${userInput}`);

  if (userInput <= 0) {
    console.log("āŒ Invalid! Please enter a positive number.\n");
  }
} while (userInput <= 0);

console.log(`āœ… Valid input accepted: ${userInput}`);
// Output:
// Input received: -5
// āŒ Invalid! Please enter a positive number.
//
// Input received: 0
// āŒ Invalid! Please enter a positive number.
//
// Input received: 42
// āœ… Valid input accepted: 42

Example 3: OTP Retry System

const correctOtp = "7291";
const otpAttempts = ["1234", "0000", "7291"]; // Simulated inputs
let otpIndex = 0;
let enteredOtp;
let maxTries = 3;
let tries = 0;

do {
  enteredOtp = otpAttempts[otpIndex++];
  tries++;
  console.log(`OTP Attempt ${tries}: ${enteredOtp}`);

  if (enteredOtp === correctOtp) {
    console.log("āœ… OTP Verified! Login successful.");
    break;
  } else {
    console.log(`āŒ Wrong OTP. ${maxTries - tries} attempt(s) remaining.`);
  }
} while (tries < maxTries);

if (enteredOtp !== correctOtp) {
  console.log("šŸ”’ Account locked. Please request a new OTP.");
}
// Output:
// OTP Attempt 1: 1234
// āŒ Wrong OTP. 2 attempt(s) remaining.
// OTP Attempt 2: 0000
// āŒ Wrong OTP. 1 attempt(s) remaining.
// OTP Attempt 3: 7291
// āœ… OTP Verified! Login successful.

Example 4: Dice Roll Until Six

// Simulate rolling a dice until we get a 6
let roll;
let rollCount = 0;
let rolls = [2, 5, 1, 4, 3, 6]; // Simulated dice rolls
let rollIndex = 0;

do {
  roll = rolls[rollIndex++];
  rollCount++;
  console.log(`Roll ${rollCount}: šŸŽ² ${roll}`);
} while (roll !== 6);

console.log(`\nšŸŽ‰ Rolled a 6 after ${rollCount} attempt(s)!`);
// Output:
// Roll 1: šŸŽ² 2
// Roll 2: šŸŽ² 5
// Roll 3: šŸŽ² 1
// Roll 4: šŸŽ² 4
// Roll 5: šŸŽ² 3
// Roll 6: šŸŽ² 6
// šŸŽ‰ Rolled a 6 after 6 attempt(s)!

Example 5: Download Retry with Backoff

// Retry a failed download up to 3 times
let downloadSuccess = false;
let attempt = 0;
let maxAttempts = 3;

// Simulate: first two fail, third succeeds
let results = [false, false, true];

do {
  attempt++;
  downloadSuccess = results[attempt - 1];

  console.log(`šŸ“„ Download attempt ${attempt}...`);

  if (downloadSuccess) {
    console.log("āœ… Download successful!");
  } else {
    console.log(`āŒ Failed. Retrying in ${attempt * 2}s...`);
  }
} while (!downloadSuccess && attempt < maxAttempts);

if (!downloadSuccess) {
  console.log("🚫 Download failed after 3 attempts. Please try again later.");
}
// Output:
// šŸ“„ Download attempt 1...
// āŒ Failed. Retrying in 2s...
// šŸ“„ Download attempt 2...
// āŒ Failed. Retrying in 4s...
// šŸ“„ Download attempt 3...
// āœ… Download successful!

break — Exit the Loop Early

// Keep generating numbers until we hit a prime
let num = 20;

do {
  num++;
  let isPrime = true;

  for (let i = 2; i < num; i++) {
    if (num % i === 0) {
      isPrime = false;
      break;
    }
  }

  if (isPrime) {
    console.log(`First prime after 20: ${num}`);
    break; // Exit do...while as soon as we find it
  }
} while (num < 100);
// Output: First prime after 20: 23

continue — Skip an Iteration

// Process a queue — skip already-processed items
let queue = ["task-1", "DONE", "task-2", "DONE", "task-3"];
let qIndex = 0;

do {
  let task = queue[qIndex];
  qIndex++;

  if (task === "DONE") {
    console.log(`ā­ļø  Skipping completed task`);
    continue;
  }

  console.log(`āš™ļø  Processing: ${task}`);
} while (qIndex < queue.length);

// Output:
// āš™ļø  Processing: task-1
// ā­ļø  Skipping completed task
// āš™ļø  Processing: task-2
// ā­ļø  Skipping completed task
// āš™ļø  Processing: task-3

Common Mistakes

Mistake 1: Missing Semicolon After while(...)

// āŒ SyntaxError — missing semicolon at the end
do {
  console.log("hello");
} while (false)  // ← missing ;

// āœ… Semicolon is required
do {
  console.log("hello");
} while (false); // āœ…

Mistake 2: Forgetting to Update the Condition Variable

let i = 1;

// āŒ i never changes — infinite loop!
do {
  console.log(i);
  // forgot i++
} while (i <= 5);

// āœ… Always update inside the body
do {
  console.log(i);
  i++; // āœ…
} while (i <= 5);

Mistake 3: Using do...while When Body Shouldn't Run if False

let isAuthenticated = false;

// āŒ do...while runs the protected code ONCE even when not authenticated!
do {
  console.log("šŸ”“ Loading dashboard..."); // Runs even though user isn't logged in!
} while (isAuthenticated);

// āœ… Use while — checks condition BEFORE running
while (isAuthenticated) {
  console.log("šŸ”“ Loading dashboard..."); // Correctly skipped āœ…
}

Mistake 4: Updating After continue — Causes Infinite Loop

let i = 1;

// āŒ When i === 3, continue jumps back BEFORE i++ — loops forever on 3!
do {
  if (i === 3) continue; // i never increments past 3!
  console.log(i);
  i++;
} while (i <= 5);

// āœ… Always increment BEFORE continue
do {
  if (i === 3) {
    i++; // āœ… Update first
    continue;
  }
  console.log(i);
  i++;
} while (i <= 5);
// Output: 1  2  4  5

Mistake 5: Confusing do...while with while for Zero-Run Scenarios

let score = 0;

// āŒ You expect this to be skipped — but it runs once!
do {
  console.log("Game over screen shown"); // Runs even with score 0
} while (score > 100);

// āœ… If the body should be conditional from start, use while
while (score > 100) {
  console.log("Game over screen shown"); // Correctly skipped āœ…
}

Practical Exercise

Create a file called do-while-loop.js:

// šŸŽÆ Do...While Loop Practice

// 1. Number guessing game simulation
console.log("=== šŸŽÆ Number Guessing Game ===");
const target = 47;
const guesses = [10, 70, 40, 55, 47];
let gIndex = 0;
let guess;
let gAttempts = 0;

do {
  guess = guesses[gIndex++];
  gAttempts++;

  if (guess < target)      console.log(`Guess ${gAttempts}: ${guess} — Too low ā¬†ļø`);
  else if (guess > target) console.log(`Guess ${gAttempts}: ${guess} — Too high ā¬‡ļø`);
  else                     console.log(`Guess ${gAttempts}: ${guess} — šŸŽ‰ Correct!`);

} while (guess !== target && gIndex < guesses.length);

console.log(`Solved in ${gAttempts} attempt(s)!\n`);


// 2. ATM PIN entry simulation
console.log("=== šŸ§ ATM PIN Entry ===");
const correctPin = "9876";
const pinAttempts = ["1111", "0000", "9876"];
let pinIndex = 0;
let pin;
let pinTries = 0;
const maxPinTries = 3;

do {
  pin = pinAttempts[pinIndex++];
  pinTries++;

  if (pin === correctPin) {
    console.log(`āœ… PIN accepted on attempt ${pinTries}. Welcome!`);
  } else {
    console.log(`āŒ Wrong PIN (Attempt ${pinTries}/${maxPinTries})`);
  }
} while (pin !== correctPin && pinTries < maxPinTries);

if (pin !== correctPin) {
  console.log("šŸ”’ Card blocked after 3 wrong attempts.\n");
}


// 3. Survey Form Simulation
console.log("=== šŸ“‹ Survey Form ===");
const questions = [
  { q: "How satisfied are you? (1-5)",  answer: 4 },
  { q: "Would you recommend us? (1-5)", answer: 5 },
  { q: "Rate our support (1-5)",        answer: 3 },
];

let qIndex = 0;
let totalRating = 0;

do {
  let current = questions[qIndex];
  totalRating += current.answer;
  console.log(`Q${qIndex + 1}: ${current.q}`);
  console.log(`Answer: ${current.answer}/5\n`);
  qIndex++;
} while (qIndex < questions.length);

let avgRating = (totalRating / questions.length).toFixed(1);
console.log(`šŸ“Š Average Rating: ${avgRating}/5`);
console.log(avgRating >= 4 ? "🌟 Excellent feedback!" : "šŸ“ Room for improvement.");

Run it:

node do-while-loop.js

Expected Output:

=== šŸŽÆ Number Guessing Game ===
Guess 1: 10 — Too low ā¬†ļø
Guess 2: 70 — Too high ā¬‡ļø
Guess 3: 40 — Too low ā¬†ļø
Guess 4: 55 — Too high ā¬‡ļø
Guess 5: 47 — šŸŽ‰ Correct!
Solved in 5 attempt(s)!

=== šŸ§ ATM PIN Entry ===
āŒ Wrong PIN (Attempt 1/3)
āŒ Wrong PIN (Attempt 2/3)
āœ… PIN accepted on attempt 3. Welcome!

=== šŸ“‹ Survey Form ===
Q1: How satisfied are you? (1-5)
Answer: 4/5

Q2: Would you recommend us? (1-5)
Answer: 5/5

Q3: Rate our support (1-5)
Answer: 3/5

šŸ“Š Average Rating: 4.0/5
🌟 Excellent feedback!

Key Takeaways

Congratulations! šŸŽ‰ You now fully understand the do...while loop in JavaScript.

āœ… do...while always runs the body at least once — the condition is checked after the first execution.

āœ… Condition at the bottom — body runs first, then condition decides if it repeats.

āœ… Semicolon required — always end with } while (condition);

āœ… Best suited for:

  • Menu systems that must display before getting input
  • Input validation — try first, validate after
  • Retry logic — attempt first, check success after
  • Any scenario where "run once, then decide" is the right approach

āœ… Avoid do...while when the body should be completely skipped if the condition is false from the start — use while instead.

āœ… break exits early. continue skips to next iteration — always update the counter before continue.


Best Practices

  1. āœ… Always add a semicolon after } while (condition); — it's easy to forget
  2. āœ… Use do...while when the body must run at least once by design
  3. āœ… Use while when the body should be skippable — don't force a run unnecessarily
  4. āœ… Always update the condition variable inside the body to avoid infinite loops
  5. āœ… When using continue, update the counter before the continue statement
  6. āœ… Keep the body focused — one clear purpose per loop
  7. āœ… Add a max attempts guard for retry-style loops to prevent runaway execution
  8. āœ… Use do...while for menus, OTP retries, validation prompts — it reads naturally

What's Next?

Great work! šŸŽ‰ You've mastered the do...while loop — the perfect tool for "try first, decide after" patterns.

Next up, let's explore the For...of Loop → — the cleanest way to loop over values of arrays, strings, and other iterables without worrying about indexes at all!

Let's keep going! šŸ’Ŗ