JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 28
  • Score
    100M100P100Q54211F
  • License MIT

A circular queue implementation with reactive features and Symbol.iterator support

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 Package

npm install reactive-circular-queue

Documentation

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 supports Symbol.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 to filledSlots === capacity;
  • empty, which corresponds to filledSlots === 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');
queue.replace(0, 'world');
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
}