FlatQueue
flatqueue is a highly optimized JavaScript priority queue implementation that leverages a binary heap structure, distinguished by storing items and their numeric priorities in two separate, flat arrays. This design choice, while limiting custom comparator functions, enables significant performance gains, often several times faster than alternatives like tinyqueue. The package is currently at version 3.0.0, primarily focused on modern JavaScript environments, being ESM-only since version 2.0.0, with further streamlining in v3.0.0 by dropping the legacy UMD bundle. It ships with first-class TypeScript types via JSDoc. Its core differentiators include its minimalistic API, small footprint, and exceptional speed, particularly effective in scenarios requiring frequent push and pop operations, making it suitable for algorithms like A* pathfinding or event schedulers where performance is critical. Its release cadence indicates active maintenance, with recent versions focusing on performance optimizations and module system compatibility, ensuring it remains a performant choice for priority queue needs in web and Node.js applications.
Common errors
-
ReferenceError: require is not defined
cause Attempting to use CommonJS `require()` to import `flatqueue` after it became an ESM-only package.fixUpdate your import statement to `import FlatQueue from 'flatqueue';` and ensure your project's `package.json` specifies `"type": "module"` if running in Node.js, or use a bundler configured for ESM. -
Perceived 'memory leak' or unexpectedly high memory usage over time.
cause The internal `ids` and `values` arrays do not automatically resize down after `pop()` or `clear()` operations to improve performance by avoiding frequent reallocations.fixCall `queue.shrink()` manually to trim the internal arrays to the current `length` of the queue, freeing unused memory. This should be done when memory usage is a concern or after significant reduction in queue size. -
TypeError: Cannot read properties of undefined (reading 'id') (or similar for other properties)
cause Attempting to access properties of the return value from `peek()` or `pop()` when the queue is empty. Both methods return `undefined` when the queue contains no items.fixAlways check if the return value of `peek()` or `pop()` is `undefined` before attempting to access its properties. For example: `const item = q.pop(); if (item !== undefined) { console.log(item.id); }`
Warnings
- breaking FlatQueue transitioned to ESM-only in v2.0.0, dropping the CommonJS entry point. In v3.0.0, the legacy UMD bundle was also removed. Direct CommonJS `require()` statements will fail.
- gotcha The `pop()` and `clear()` methods do not automatically shrink the internal arrays (`ids` and `values`) to free memory. This behavior is intentional to improve performance by avoiding unnecessary reallocations during intensive reuse, but can lead to higher memory consumption if the queue size frequently fluctuates downwards and isn't explicitly managed.
- gotcha FlatQueue is not 'stable' for items with identical priority values. If multiple items share the same lowest priority, there is no guarantee which of them will be returned first by `pop()` or `peek()`.
- gotcha For maximum performance and memory efficiency, especially when the maximum queue size is known, you can override the internal `ids` and `values` arrays with typed arrays (e.g., `Uint16Array`, `Uint32Array`).
Install
-
npm install flatqueue -
yarn add flatqueue -
pnpm add flatqueue
Imports
- FlatQueue
const FlatQueue = require('flatqueue');import FlatQueue from 'flatqueue';
- FlatQueue (CDN)
import FlatQueue from 'https://cdn.jsdelivr.net/npm/flatqueue/+esm';
- TypeScript Types
import FlatQueue from 'flatqueue'; // Types are inferred via JSDoc
Quickstart
import FlatQueue from 'flatqueue';
interface Item {
id: number;
priority: number;
data: string;
}
const q = new FlatQueue();
const items: Item[] = [
{ id: 0, priority: 5, data: 'task A' },
{ id: 1, priority: 1, data: 'task B' },
{ id: 2, priority: 8, data: 'task C' },
{ id: 3, priority: 2, data: 'task D' }
];
console.log('Pushing items...');
for (let i = 0; i < items.length; i++) {
// Push the item's original ID (or the item itself) and its priority value.
// Storing only integers (like IDs/indices) is generally faster for JavaScript engine optimizations.
q.push(items[i].id, items[i].priority);
}
console.log(`\nQueue length: ${q.length}`);
console.log(`Top item (ID): ${q.peek()}`); // Expected: 1 (ID of task B)
console.log(`Top item priority: ${q.peekValue()}`); // Expected: 1
const poppedId = q.pop(); // Removes ID 1
console.log(`Popped item ID: ${poppedId}`); // Expected: 1
console.log(`\nNew top item (ID): ${q.peek()}`); // Expected: 3 (ID of task D)
console.log(`New top item priority: ${q.peekValue()}`); // Expected: 2
q.clear();
console.log(`\nQueue length after clear: ${q.length}`); // Expected: 0