JavaScriptWhile & Do-While Loops

while and do-while

while is the simplest loop in JavaScript: while this condition is true, keep going. There's no counter to set up and no increment to remember — just a question. Use it when you don't know in advance how many iterations you need, like reading from a stream, retrying a request, or walking a tree until you hit the root.

The while loop

The condition is checked before each iteration. If it is falsy at the start, the body never runs.

JS
let n = 1;
while (n < 100) {
  n *= 2;
}
console.log(n);    // 128 — first power of two >= 100
128

Compare to a classic for loop: same job, but while doesn't pretend there's a counter when really we just care about a condition.

Reading until exhausted

Whenever you have a producer that yields data and signals "no more" somehow, while reads beautifully.

JS
function consumeQueue(queue) {
  while (queue.length > 0) {
    const job = queue.shift();
    handle(job);
  }
}

Walking up a DOM tree

JS
let node = startNode;
while (node && node !== document.body) {
  if (node.classList.contains("highlight")) break;
  node = node.parentElement;
}
do-while: run first, ask later

do { ... } while (cond) flips the order: the body runs first, then the condition is checked. The body is guaranteed to run at least once.

JS
let answer;
do {
  answer = prompt("Type 'yes' to continue");
} while (answer !== "yes");

The classic use case is prompt-then-validate: ask the user a question, and keep asking until the answer is acceptable. With a plain while you'd need a flag or a redundant first read.

Choosing between them

The difference is just when the check happens:

  • Use while when there is a chance the loop should not run at all. Reading from an empty queue, polling for a flag that might already be set.

  • Use do...while when you need at least one pass — running a step, then deciding whether to repeat.

  • Use for when there is an explicit counter or a fixed range.

Same logic, different shape

JS
// while — 0 iterations if items is already empty
while (items.length > 0) {
  process(items.pop());
}

// do-while — always at least 1 iteration, even if items is empty
do {
  process(items.pop());
} while (items.length > 0);
Infinite loops and clean breaks

while (true) is a deliberate infinite loop. You always pair it with at least one break (or return, or throw) inside the body.

Retry with backoff

JS
async function fetchWithRetry(url, maxAttempts = 5) {
  let attempt = 0;
  while (true) {
    try {
      return await fetch(url);
    } catch (err) {
      attempt++;
      if (attempt >= maxAttempts) throw err;
      await sleep(2 ** attempt * 100);   // 200ms, 400ms, 800ms, ...
    }
  }
}

Two things make this readable: the only way out is success or running out of attempts, and the structure mirrors the English description ("try, if it fails wait and try again").

Accidental infinite loops
Forgetting to change the condition
The most common bug is a loop body that doesn't make progress towards the condition becoming false. Browsers will eventually pop a "slow script" dialog; Node will just sit there pinning a CPU core.

The classic mistake

JS
let i = 0;
while (i < 10) {
  console.log(i);
  // forgot to increment i — runs forever
}

Defences:

  • Always update the variable that controls the condition inside the loop.

  • When the condition involves an external source (a queue, a stream), make sure that source actually drains.

  • Add a sanity-check counter that throws after, say, 100k iterations during development.

Belt and braces

JS
let guard = 0;
while (notDoneYet()) {
  step();
  if (++guard > 100_000) throw new Error("loop limit exceeded");
}
break and continue

Both work exactly as in for. break ends the loop; continue jumps to the next condition check.

JS
while (input = readLine()) {
  if (input.startsWith("#")) continue;   // skip comments
  if (input === "END") break;            // stop on sentinel
  process(input);
}
Assigning inside a condition
`while ((input = readLine()))` is idiomatic for "read until the read returns falsy". Wrap the assignment in extra parens to silence linters that suspect a typo.
while vs recursion

Many problems can be expressed either as a loop or as a recursive function. When the recursion depth is unbounded, prefer while — JavaScript engines don't reliably eliminate tail calls, so deep recursion blows the stack.

Tree traversal — iterative form

JS
function findFirst(root, predicate) {
  const stack = [root];
  while (stack.length > 0) {
    const node = stack.pop();
    if (predicate(node)) return node;
    if (node.children) stack.push(...node.children);
  }
  return null;
}
One sentence to remember
Use `while` for "keep going until X stops being true", `do...while` when you need at least one pass, and `while (true)` only when the exit is an explicit `break` or `return`.