Package Exports
- reactive-circular-queue
- reactive-circular-queue/package.json
Readme
reactive-circular-queue
A circular queue implementation with reactive features and Symbol.iterator support.
A circular queue (or ring buffer, or circular buffer) is a data structure where elements can be stored and removed without reallocating the underline array. It's often used to implement First In-First Out queues.
npm install reactive-circular-queue
Highlights
CircularQueue<T>
provides methods such as:
enqueue(value)
, to enqueue a single value;enqueueMulti([value1, value2, ...])
, to enqueue multiple values;dequeue()
, to dequeue a single value;dequeue(n)
, to dequeue n values;dequeueAll()
, to dequeue all elements at once;clear()
, to remove all elements from the queue;toArray()
, to create an array containing the elements in the queue;at(index)
, to read (without dequeueing) an element in the queue at a given index (positive or negative);replace(index, item)
, to replace (without affecting the queue size) an element in the queue at a given index (positive or negative);iter()
, to get an iterator that dequeues elements one at a time (it also supportsSymbol.iterator
, see the example below).
It also provides the following getters:
availableSlots
, corresponding to the number of empty slots still available in the queue;filledSlots
, corresponding to the number of filled slots in the queue;capacity
, corresponding to the total number of slots in the queue, available or filled;full
, which corresponds tofilledSlots === capacity
;empty
, which corresponds tofilledSlots === 0
.
Each getters has a corresponding ReadonlyStore
: availableSlots$
, filledSlots$
, capacity$
, full$
, empty$
.
These stores make this circular queue implementation reactive.
This library provides a function called makeCircularQueue
to create CircularQueue<T>
objects.
This function has two overloads:
makeCircularQueue(capacity)
, which takes the maximum size of the queue as its only parameter;makeCircularQueue(array, capacity)
, which takes an array that will be used to initialize the queue as its first parameter and a second optional parameter which is the capacity of the queue. If the capacity is not passed, the array length will be used to determine the maximum queue size.
import {makeCircularQueue} from 'reactive-circular-queue';
// Create an empty queue that can hold up to 3 items.
const queue1 = makeCircularQueue<string>(3);
console.log(queue1.capacity); // 3
console.log(queue1.filledSlots); // 0
// Create a full queue that can hold up to 3 items (deduced from the array length).
const queue2 = makeCircularQueue(['hello', 'world', '!']);
console.log(queue2.capacity); // 3
console.log(queue2.filledSlots); // 3
// Create an almost full queue that can hold up to 3 items (as per the second argument).
const queue3 = makeCircularQueue(['hello', 'world'], 3);
console.log(queue3.capacity); // 3
console.log(queue3.filledSlots); // 2
// Create a full queue that can hold up to 2 items (as per the second argument).
const queue4 = makeCircularQueue(['hello', 'world', '!'], 2);
console.log(queue4.capacity); // 2
console.log(queue4.filledSlots); // 2, only 'hello' and 'world' were copied inside the queue.
Examples
Basics:
const queue = makeCircularQueue<string>(3);
queue.enqueue('hello');
queue.enqueue('world');
queue.enqueue('!');
console.log(queue.dequeue()); // hello
console.log(queue.dequeue()); // world
queue.enqueue('bye');
console.log(queue.toArray().join(', ')); // !, bye
Reactivity:
const queue = makeCircularQueue<string>(3);
queue.filledSlots$.subscribe((n) => console.log(`using ${n} of ${queue.capacity} slots`)); // immediately prints "using 0 of 3 slots"
queue.enqueue('hello'); // will trigger the above console.log, printing "using 1 of 3 slots"
queue.enqueue('world'); // will trigger the above console.log, printing "using 2 of 3 slots"
queue.enqueue('!'); // will trigger the above console.log, printing "using 3 of 3 slots"
queue.dequeue(); // will trigger the above console.log, printing "using 2 of 3 slots"
queue.dequeue(); // will trigger the above console.log, printing "using 1 of 3 slots"
queue.enqueue('bye'); // will trigger the above console.log, printing "using 2 of 3 slots"
console.log(queue.toArray().join(', ')); // !, bye
Usage of enqueueMulti
:
const queue = makeCircularQueue<string>(3);
queue.enqueueMulti(['hello', 'world']);
queue.enqueue('!');
console.log(queue.toArray().join(', ')); // hello, world, !
Usage of dequeue(n)
:
const queue = makeCircularQueue<string>(3);
queue.enqueueMulti(['hello', 'world']);
queue.enqueue('!');
console.log(queue.dequeue(2).join(', ')); // hello, world
console.log(queue.dequeue()); // !
Usage of dequeueAll(n)
:
const queue = makeCircularQueue<string>(3);
queue.enqueueMulti(['hello', 'world']);
queue.enqueue('!');
console.log(queue.dequeueAll().join(', ')); // hello, world, !
Usage of at(i)
:
const queue = makeCircularQueue<string>(3);
queue.enqueueMulti(['hello', 'world']);
console.log(queue.at(0)); // hello
console.log(queue.at(1)); // world
console.log(queue.at(2)); // undefined
console.log(queue.at(-1)); // world
console.log(queue.at(-2)); // hello
Usage of replace(i, item)
:
const queue = makeCircularQueue<string>(1);
queue.enqueue('hello');
console.log(queue.replace(0, 'world')); // hello
console.log(queue.dequeue()); // world
Usage with for..of
([Symbol.iterator]()
):
const queue = makeCircularQueue<string>(3);
queue.enqueueMulti(['hello', 'world']);
console.log(queue.filledSlots); // 2
for (const value of queue) {
console.log(value); // prints hello, then world
console.log(queue.filledSlots); // prints 1, then 0
}