RepoPilot

Show me how the concurrency limiter actually queues tasks.

About sindresorhus/p-limit · 2 messages · last activity 7/6/2026

Question

Show me how the concurrency limiter actually queues tasks.

RepoPilot

Perfect! Now I have the complete implementation. Here's how the concurrency limiter queues tasks:

Queue Implementation Overview

The core queuing logic is in [index.js:L3-L116]. The system uses a Queue data structure (from the yocto-queue dependency) to manage pending tasks and three key mechanisms to control concurrency:

1. Enqueuing Tasks [index.js:L47-L57]

When you call limit(function_, ...args), the enqueue function:

  • Wraps the task in a queue item with a reject handler
  • Creates a promise with an internalResolve callback that gets stored in queueItem.run
  • Adds the item to the queue via queue.enqueue(queueItem)
  • If activeCount < concurrency, immediately triggers resumeNext() to start execution

2. Processing the Queue [index.js:L20-L25]

resumeNext() is the engine:

  • Checks if there's room to run more tasks: activeCount < concurrency && queue.size > 0
  • If yes, increments activeCount and calls queue.dequeue().run() to execute the next queued item
  • The dequeued run callback triggers the promise chain that executes the actual function

3. Completing Tasks [index.js:L27-L45]

When a task executes via the run function:

  • The user's function is called and wrapped in an async IIFE
  • The result promise is immediately resolved to the caller (doesn't wait for completion)
  • The implementation awaits the result internally to catch completion/errors
  • Once done, calls next() which:
    • Decrements activeCount
    • Calls resumeNext() to dequeue and start the next pending task

4. State Tracking [index.js:L59-L63, L64-L66]

  • activeCount: Number of currently running tasks (read-only property)
  • queue.size: Available via pendingCount property, tracks waiting tasks

Example Flow

With pLimit(2) and 5 tasks:

  1. Tasks 1–2 execute immediately (activeCount = 2)
  2. Tasks 3–5 queue (pendingCount = 3)
  3. When task 1 completes, next() triggers resumeNext()
  4. Task 3 dequeues and runs (activeCount = 2, pendingCount = 2)
  5. Pattern repeats until all tasks finish

The dependency on yocto-queue [package.json:L38] provides an efficient FIFO queue implementation for this pattern.

FOLLOW_UPS:

  • How does clearQueue() handle pending task rejections?
  • What happens if concurrency is changed mid-execution?
  • Why resolve immediately instead of waiting for completion?

Want to ask your own question?

Open chat for sindresorhus/p-limit

Public Q&A. Generated by RepoPilot from the actual source of sindresorhus/p-limit. AI answers can be incomplete or stale — verify before relying on them.