RepoPilot

Show me how the concurrency limiter actually queues tasks.

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

Question

Show me how the concurrency limiter actually queues tasks.

RepoPilot

The concurrency limiter uses a queue-based architecture to manage task execution. Here's how it works:

Task Queueing Process

When you call the limit function with a task, the enqueue function handles queuing [index.js:L50-L62]:

const enqueue = (function_, resolve, reject, arguments_) => {
	const queueItem = {reject};

	// Queue the internal resolve function instead of the run function
	// to preserve the asynchronous execution context.
	new Promise(internalResolve => { // eslint-disable-line promise/param-names
		queueItem.run = internalResolve;
		queue.enqueue(queueItem);
	}).then(run.bind(undefined, function_, resolve, arguments_)); // eslint-disable-line promise/prefer-await-to-then

	// Start processing immediately if we haven't reached the concurrency limit
	if (activeCount < concurrency) {
		resumeNext();
	}
};

The Queue Data Structure

The queue stores queueItem objects, each containing a reject function and a run function. The run function is set to internalResolve when the item is enqueued.

Task Execution Flow

  1. Immediate Start: If activeCount < concurrency, resumeNext() is called immediately [index.js:L61-L62]

  2. resumeNext Logic [index.js:L18-L22]:

const resumeNext = () => {
	// Process the next queued function if we're under the concurrency limit
	if (activeCount < concurrency && queue.size > 0) {
		activeCount++;
		queue.dequeue().run();
	}
};
  1. Task Execution: When queue.dequeue().run() is called, it triggers the run function [index.js:L27-L44], which:

    • Executes the actual function
    • Resolves the promise immediately (without waiting)
    • Awaits completion internally
    • Calls next() to decrement activeCount and process the next queued task
  2. Cleanup: The next() function [index.js:L24-L26] decrements the active count and calls resumeNext() to process the next item if queue space is available.

This creates a pipeline where tasks are queued until concurrency slots open up, maintaining the concurrency limit throughout execution.

FOLLOW_UPS:

  • How does the clearQueue method work exactly?
  • What happens if concurrency limit is changed dynamically?
  • How does the map function leverage the queue system?

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.