← All concepts
Queues

Queues

A queue only lets you add at the back and remove from the front: first in, first out.

Definition

A queue is a collection with two distinct ends. Adding an item, enqueue, always happens at the back, and removing an item, dequeue, always happens at the front. That keeps the order items come out matching the order they went in: first in, first out (FIFO), the opposite of a stack's last-in-first-out order. Queues show up wherever things need to be handled in arrival order. Breadth-first search visits nodes level by level by keeping a queue of nodes still to visit. The event loop's macrotask (callback) queue runs scheduled callbacks in the order they became ready. A naive array-backed queue can dequeue with shift, but that is an O(n) operation because every remaining element has to move down one slot; a queue meant for heavy use is usually backed by a linked list or by tracking a separate front index so dequeue stays O(1).

Examples

const queue = [];
queue.push(1); // enqueue
queue.push(2);
queue.push(3);
queue.shift(); // 1 (dequeue)
queue; // [2, 3]

push adds to the back and shift removes from the front, so the first value enqueued, 1, is the first one dequeued.

function bfs(graph, start) {
  const visited = new Set([start]);
  const queue = [start];
  const order = [];
  while (queue.length) {
    const node = queue.shift();
    order.push(node);
    for (const next of graph[node]) {
      if (!visited.has(next)) {
        visited.add(next);
        queue.push(next);
      }
    }
  }
  return order;
}
bfs({ a: ["b", "c"], b: ["d"], c: [], d: [] }, "a"); // ["a", "b", "c", "d"]

Each node's neighbors are enqueued at the back, so the traversal visits every node one level away before moving on to the next level.

class Queue {
  #items = [];
  #front = 0;
  enqueue(v) { this.#items.push(v); }
  dequeue() {
    if (this.#front >= this.#items.length) return undefined;
    return this.#items[this.#front++];
  }
}
const q = new Queue();
q.enqueue("a");
q.enqueue("b");
q.dequeue(); // "a"

Tracking a front index instead of calling shift avoids re-numbering every remaining element, keeping dequeue O(1).

Common mistakes

  • Using Array.prototype.shift() to dequeue from a large array in a hot loop; shift is O(n) because every remaining element moves down.
  • Mixing up which end is which; enqueue always adds at the back, dequeue always removes from the front.
  • Forgetting to check for an empty queue before dequeuing and getting undefined instead of handling the empty case explicitly.

Key takeaways

  • FIFO ordering means the first item added is the first one removed.
  • Enqueue happens at the back, dequeue happens at the front, and the two ends stay conceptually separate.
  • An array-backed queue works, but a front-index or linked-list backed queue avoids the O(n) cost of shifting elements.
Check your understanding

You enqueue 1, then 2, then 3. What does the first dequeue() call return?

Where you see this

  • Breadth-first search, visiting nodes level by level.
  • Task or job scheduling, processing requests in the order they arrived.
  • The event loop's macrotask queue, running callbacks in the order they became ready.
  • Rate limiting or buffering, holding incoming items until they can be processed.

Practice this

Further reading

Previous
Stacks
Next
Linked Lists